2014-05-03 3 views
1

ualarm() n'est pas implémenté dans la version Android de libc, bionic (vérifiez Bionic unistd.h). De plus, ualarm() est obsolète.ualarm() équivalent (Android Bionic libc)

Je portage d'une application sur Android NDK donc je besoin d'un équivalent de ualarm (999999,999999), à savoir quelque chose qui enverrait un SIGALRM périodiquement (chaque seconde).

Peut-être avec timer_create()? Il semble être implemented in Bionic. Mais l'exemple dans la page man est vraiment pas trivial ...

code Je suis willign au port à Android (NDK):

/* 
* Set a recurring 1 second timer that will call sigalrm() and switch to 
* a new channel. 
*/ 

    act.sa_handler = sigalrm_handler; 
    sigaction (SIGALRM, &act, 0); 
    ualarm(CHANNEL_INTERVAL, CHANNEL_INTERVAL); 
    change_channel(1); 

/* Whenever a SIGALRM is thrown, go to the next 802.11 channel */ 
void sigalrm_handler(int x) 
{ 
    next_channel(); 
} 
+0

La réponse est dans la page de manuel Linux ualarm(): 'Cette fonction est obsolète. Utilisez setitimer (2) ou les temporisateurs d'intervalle POSIX (timer_create (2), etc.) à la place. » – fadden

+0

Merci, mais c'est pourquoi j'ai pensé à la question. Je viens de passer une heure pour faire les choses avec le code approprié. Et 1 heure de plus pour créer le code de minuterie de suppression comme ualarm (0, 0) équivalent nécessite une référence de minuterie ... (mettra à jour la réponse pour cela). – KrisWebDev

Répondre

0

OK, create_timer était la clé. Dommage que personne n'ait répondu avec un exemple à temps.

J'ai construit ce code en simplifiant this answer.

#include <stdlib.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <signal.h> 
#include <time.h> 

// Handler that will be called every its.it_value.tv_sec seconds + its.it_value.tv_nsec nanoseconds until you kill the timer 
static void handler(int sig, siginfo_t *si, void *uc) 
{ 
     printf("Caught signal %d from timer\n", sig); 
} 

int main(int argc, char *argv[]) 
{ 
    struct sigevent sev; 
    struct itimerspec its; 
    sigset_t mask; 
    struct sigaction sa; 
    timer_t timerid; 

    // Define sigaction: handler 
    sa.sa_flags = SA_SIGINFO; 
    sa.sa_sigaction = handler; 
    sigemptyset(&sa.sa_mask); 
    sigaction(SIGUSR1, &sa, NULL); 

    // Define sigevent 
    sev.sigev_notify = SIGEV_SIGNAL; 
    sev.sigev_signo = SIGUSR1; 

    // Create the timer 
    timer_create(CLOCK_REALTIME, &sev, &timerid); 
    its.it_value.tv_sec = 1; 
    its.it_value.tv_nsec = 0; 
    its.it_interval.tv_sec = its.it_value.tv_sec; 
    its.it_interval.tv_nsec = its.it_value.tv_nsec; 
    timer_settime(timerid, 0, &its, NULL); 

    // Sleeps (100sec) is aborted: its default behavior is to wake up when a signal is received (1sec) 
    // So we sleep again to properly see the next signal in this example. 
    // That's just for the example so that the process doesn't terminate. 
    sleep(100); sleep(100); sleep(100); sleep(100); sleep(100); sleep(100); 
    exit(EXIT_SUCCESS); 
} 

La désactivation d'un temporisateur périodique a été effectuée avec ualarm (0, 0). Il n'y avait pas besoin de passer une minuterie en argument. Mais avec time_delete, nous avons besoin de cette référence de timer. Le code doit donc être adapté pour mémoriser la référence de la minuterie pour la désactiver.

Donc, pour passer le minuteur en référence si nécessaire:

some_function(..., &timerid); 
void some_function(..., timer_t *timerid) 

Et pour désactiver la minuterie:

timer_delete(timerid); 

Notez également que ualarm utilise SIGALRM. Dans ce code, nous utilisons SIGUSR1 à la place.

SIGALRM, sigvtalrm et SIGPROF Le SIGALRM, sigvtalrm et le signal SIGPROF est envoyé à un processus lorsque la limite de temps spécifiée dans un appel à une fonction de réglage d'alarme précédent (tel que setitimer) soit écoulé. SIGALRM est envoyé lorsque le temps réel ou s'écoule. SIGVTALRM est envoyé lorsque le temps CPU utilisé par le processus est écoulé. SIGPROF est envoyé lorsque le temps CPU utilisé par le processus et par le système au nom du processus se termine. SIGUSR1 et SIGUSR2 Les signaux SIGUSR1 et SIGUSR2 sont envoyés à un processus pour indiquer les conditions définies par l'utilisateur.

Il peut y avoir des conflits de temporisation si vous utilisez plusieurs temporisateurs qui utilisent tous SIGUSR1. Vérifiez le original answer pour gérer plusieurs minuteries tout en utilisant SIGUSR1.