Эквивалент 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();
}
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 отправляется процессу, когда истекает лимит времени, указанный в вызове предыдущей функции настройки будильника (такой как setitimer). SIGALRM отправляется по истечении реального или часового времени. SIGVTALRM отправляется по истечении времени ЦП, используемого процессом. SIGPROF отправляется по истечении времени ЦП, используемого процессом и системой от имени процесса.
SIGUSR1 и SIGUSR2 Сигналы SIGUSR1 и SIGUSR2 отправляются процессу для индикации пользовательских условий.
Могут быть конфликты таймера, если вы используете несколько таймеров, которые все используют SIGUSR1. Проверьте исходный ответ для обработки нескольких таймеров, использующих SIGUSR1.