Эквивалент ualarm() (Android Bionic libc)

ualarm() не реализован в Android-версии libc, bionic (отметьте Bionic unistd.h). Более того, ualarm() устарела.

Я переношу приложение на Android NDK, поэтому мне нужен аналог ualarm(999999,999999), т.е. что-то, что будет отправлять SIGALRM периодически (каждую секунду).

Может быть, с timer_create()? Кажется, это реализовано в Bionic. Но пример на странице руководства действительно не тривиален...

Код, который я собираюсь портировать на 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();
}

person KrisWebDev    schedule 03.05.2014    source источник
comment
Ответ находится на справочной странице Linux ualarm(): This function is obsolete. Use setitimer(2) or POSIX interval timers (timer_create(2), etc.) instead.   -  person fadden    schedule 03.05.2014
comment
Спасибо, но именно поэтому я подумал в вопросе. Я только что потратил 1 час, чтобы сделать что-то с соответствующим кодом. И еще 1 час для создания кода таймера удаления, поскольку для эквивалента ualarm (0, 0) требуется ссылка на таймер... (для этого будет обновлен ответ).   -  person KrisWebDev    schedule 03.05.2014


Ответы (1)


Хорошо, create_timer был ключом. Жаль, что никто вовремя не ответил с примером.

Я создал этот код, упростив этот ответ.

#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);
}

Отключение периодического таймера было выполнено с помощью ualarm(0, 0). Не было необходимости передавать таймер в аргументе. Но с time_delete нам нужна эта ссылка на таймер. Поэтому код должен быть адаптирован для запоминания ссылки на таймер, чтобы отключить его.

Итак, чтобы передать таймер по ссылке, если это необходимо:

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

И чтобы отключить таймер:

timer_delete(timerid);

Также обратите внимание, что ualarm использует сигнал SIGALRM. В этом коде вместо этого мы используем SIGUSR1.

SIGALRM, SIGVTALRM и SIGPROF Сигналы SIGALRM, SIGVTALRM и SIGPROF отправляются процессу, когда истекает ограничение времени, указанное в вызове предшествующей функции настройки аварийного сигнала (например, settimer). Сигнал SIGALRM отправляется по истечении реального или часового времени. SIGVTALRM отправляется, когда истекает время ЦП, используемое процессом. SIGPROF отправляется, когда время ЦП, используемое процессом и системой от имени процесса, истекает.

SIGUSR1 и SIGUSR2 Сигналы SIGUSR1 и SIGUSR2 отправляются процессу для указания определенных пользователем условий.

Могут возникнуть конфликты таймеров, если вы используете несколько таймеров, все из которых используют SIGUSR1. Проверьте исходный ответ, чтобы обработать несколько таймеров, использующих SIGUSR1.

person KrisWebDev    schedule 03.05.2014