【问题标题】:ualarm() equivalent (Android Bionic libc)ualarm() 等效项(Android Bionic libc)
【发布时间】:2014-05-03 17:25:16
【问题描述】:

ualarm() 未在 Android 版本的 libc、bionic 中实现(检查 Bionic unistd.h)。此外,ualarm() 已过时。

我在 Android NDK 上移植一个应用程序,所以我需要一个等效的 ualarm(999999,999999),即会定期发送 SIGALRM(每秒)的东西.

也许timer_create() ?好像是implemented in Bionic。但是man page中的例子真的不简单……

我愿意移植到 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();
}

【问题讨论】:

  • 答案在 Linux ualarm() 手册页中:This function is obsolete. Use setitimer(2) or POSIX interval timers (timer_create(2), etc.) instead.
  • 谢谢,但这就是我在这个问题中想到的原因。我刚刚花了 1 个小时来完成相关代码的工作。还有 1 个小时来创建删除计时器代码,因为 ualarm(0, 0) 等效项需要计时器参考...(将更新答案)。

标签: android linux android-ndk libc bionic


【解决方案1】:

好的,create_timer 是关键。可惜没有人及时给出例子。

我通过简化 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);
}

使用 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 在 CPU 时间被 过程过去。 SIGPROF 在进程使用 CPU 时间时发送,并且 由系统代表进程过去。

SIGUSR1 和 SIGUSR2 SIGUSR1 和 SIGUSR2 信号被发送到进程以指示用户定义的条件。

如果您使用多个都使用 SIGUSR1 的计时器,则可能会发生计时器冲突。检查original answer 来处理多个使用SIGUSR1 的计时器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-20
    • 1970-01-01
    • 1970-01-01
    • 2012-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-03
    相关资源
    最近更新 更多