在在C linux的定时器 [英] timers in linux in c

查看:136
本文介绍了在在C linux的定时器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可能重复:结果
  环路/用C 定时器

我一直在阅读有关计时器的最后3天,我无法找到任何有用的,我想了解它在真实的例子,有人可以帮我找出如何设置警报的下方程序。

I've been reading about timers for the last 3 days and I'm unable to find anything useful, I'm trying to understand it in real example, can somebody help me figure out how to setup an alarm for the below program.

如何设置AA定时器,使得它会发出2 ARGS,一个是数组名,第二个是要删除的号码,我知道反正下面是不是安全的,我只是想了解如何使用报警与args设置为调用一个函数。

How can I set a a timer so that it will send 2 args, one is the array name, and the second one is the number to be deleted, I know the below is not safe in anyway, I'm just trying to understand how use alarms with args to call a function.

请注意,环境的Linux,也是我AP preciate与运行的C例子任何链接。

please note that the environment is Linux, and also I appreciate any link with a working C example.

#include<stdio.h>
int delete_from_array(int arg) ;


    int main()
    {

    int a[10000], i, y ;
    //how to set timer here for to delete any number in array after half a second
    for (y=0; y < 100; y++) {


        for (i=0; i<sizeof(a) / sizeof(int); i++)
            a[i] = i;
    sleep(1);
    printf("wake\n");
    }

    }

    int delete_from_array(int arg) 
    {
    int i, a[1000], number_to_delete=0;

    //number_to_delete = arg->number;

    for (i=0; i<sizeof(a); i++)
        if (a[i] == number_to_delete)
            a[i] = 0;
    printf("deleted\n");

    }

我想要做的是,我有有已经值设置为1秒后过期的哈希,所以我该值插入散后,我需要创建一个定时器,使得它会删除该值让后说1秒,如果我得到了来自该时间间隔(1秒)之前服务器的响应,然后我从哈希删除值,并删除定时器,简直就像在TCP重传

What I'm trying to do is that I have a hash which has has values to be expired after 1 seconds, so after I insert the value into the hash, I need to create a timer so that it will delete that value after let's say 1 second, and IF I got a response from the server before the that interval (1 second) then I delete the value from the hash and delete the timer, almost like retransmission in tcp

推荐答案

你想使用的信号或线程?

Do you want to use signals or threads?

首先,设置信号处理程序或prepare合适的线程函数;看到人7的sigevent 了解详细信息。

First, set up the signal handler or prepare a suitable thread function; see man 7 sigevent for details.

接下来,创建一个合适的定时器,用 timer_create()。请参见人2 timer_create 了解详细信息。

Next, create a suitable timer, using timer_create(). See man 2 timer_create for details.

根据你做什么时,计时器火灾,你不妨定时器设置为一次性,或在短的时间间隔后重复。您可以使用 timer_settime()这两个手臂,解除武装,定时器;看到人2 timer_settime 了解详细信息。

Depending on what you do when the timer fires, you may wish to set the timer to either one-shot, or to repeat at a short interval afterwards. You use timer_settime() to both arm, and to disarm, the timer; see man 2 timer_settime for details.

在实际应用中通常需要复用计时器。即使一个进程可以创建多个定时器,它们是一种有限的资源。尤其超时定时器 - 这是微不足道的,无论是设置一个标志和/或将信号发送到一个特定的线程 - 应该使用一个定时器,该触发在下一超时,设置相关的超时标志,以及可选地发送的信号(用空体处理),以所需的螺纹,以确保它被中断。 (对于单线程的过程中,原有的信号传递将中断阻塞I / O调用)。考虑一个服务器,响应一些请求:请求本身可能有一分钟左右的量级超时,在处理请求可能需要连接超时,I / O超时,等等。

In practical applications you usually need to multiplex the timer. Even though a process can create multiple timers, they are a limited resource. Especially timeout timers -- which are trivial, either setting a flag and/or sending a signal to a specific thread -- should use a single timer, which fires at the next timeout, sets the related timeout flag, and optionally send a signal (with an empty-body handler) to the desired thread to make sure it is interrupted. (For a single-thread process, the original signal delivery will interrupt blocking I/O calls.) Consider a server, responding to some request: the request itself might have a timeout on the order of a minute or so, while processing the request might need connection timeouts, I/O timeouts, and so on.

现在,原来的问题是有趣的,因为有效使用定时器的时候都强大。但是,示例程序基本上是无稽之谈。你为什么不创建说程序设置一个或多个定时器,每个例如东西输出到标准输出?请记住,使用的write()等从 unistd.h中人,因为他们的异步信号安全,而的printf()等从 stdio.h中都没有。 (如果你的信号处理程序使用非异步信号安全功能,结果是不确定的,通常的工作原理,但它并不保证;它可能只是以及崩溃的工作测试不会告诉,因为它的未定义的。)

Now, the original question is interesting, because timers are powerful when used effectively. However, the example program is basically nonsense. Why don't you create say a program that sets one or more timers, each for example outputting something to standard output? Remember to use write() et al from unistd.h as they are async-signal safe, whereas printf() et cetera from stdio.h are not. (If your signal handlers use non-async-signal safe functions, the results are undefined. It usually works, but it's not guaranteed at all; it may just as well crash as work. Testing will not tell, as it is undefined.)

编辑补充:这里是复用超时的一个最基本的例子

Edited to add: Here is a bare-bones example of multiplexed timeouts.

(根据法律允许的范围内,我奉献所有版权及相关权利以如下全球公共领域的code片段;看到的 CC0公共领域贡献。换句话说,随时在你希望的任何方式使用code以下,就不要怪我任何问题用它。)

(To the extent possible under law, I dedicate all copyright and related and neighboring rights to the code snippets shown below to the public domain worldwide; see CC0 Public Domain Dedication. In other words, feel free to use the code below in any way you wish, just don't blame me for any problems with it.)

我用旧式GCC原子内置插件,所以它应该是线程安全的。有一些补充,应该多线程code工作了。 (您不能使用,例如互斥,因为 pthread_mutex_lock()的不是异步信号安全的。以原子操作超时状态应该工作,虽然可能有一些比赛留给如果禁用超时只是当它闪光。)

I used old-style GCC atomic built-ins, so it should be thread-safe. With a few additions, it should work for multithreaded code too. (You cannot use for example mutexes, because pthread_mutex_lock() is not async-signal safe. Atomically manipulating the timeout states should work, although there might be some races left if you disable a timeout just when it fires.)

#define _POSIX_C_SOURCE 200809L
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <errno.h>

#define   TIMEOUTS       16
#define   TIMEOUT_SIGNAL (SIGRTMIN+0)

#define   TIMEOUT_USED   1
#define   TIMEOUT_ARMED  2
#define   TIMEOUT_PASSED 4

static timer_t               timeout_timer;
static volatile sig_atomic_t timeout_state[TIMEOUTS] = { 0 };
static struct timespec       timeout_time[TIMEOUTS];


/* Return the number of seconds between before and after, (after - before).
 * This must be async-signal safe, so it cannot use difftime().
*/
static inline double timespec_diff(const struct timespec after, const struct timespec before)
{
    return (double)(after.tv_sec - before.tv_sec)
         + (double)(after.tv_nsec - before.tv_nsec) / 1000000000.0;
}

/* Add positive seconds to a timespec, nothing if seconds is negative.
 * This must be async-signal safe.
*/
static inline void timespec_add(struct timespec *const to, const double seconds)
{
    if (to && seconds > 0.0) {
        long  s = (long)seconds;
        long  ns = (long)(0.5 + 1000000000.0 * (seconds - (double)s));

        /* Adjust for rounding errors. */
        if (ns < 0L)
            ns = 0L;
        else
        if (ns > 999999999L)
            ns = 999999999L;

        to->tv_sec += (time_t)s;
        to->tv_nsec += ns;

        if (to->tv_nsec >= 1000000000L) {
            to->tv_nsec -= 1000000000L;
            to->tv_sec++;
        }
    }
}

/* Set the timespec to the specified number of seconds, or zero if negative seconds.
*/
static inline void timespec_set(struct timespec *const to, const double seconds)
{
    if (to) {
        if (seconds > 0.0) {
            const long  s = (long)seconds;
            long       ns = (long)(0.5 + 1000000000.0 * (seconds - (double)s));

            if (ns < 0L)
                ns = 0L;
            else
            if (ns > 999999999L)
                ns = 999999999L;

            to->tv_sec = (time_t)s;
            to->tv_nsec = ns;

        } else {
            to->tv_sec = (time_t)0;
            to->tv_nsec = 0L;
        }
    }
}


/* Return nonzero if the timeout has occurred.
*/
static inline int timeout_passed(const int timeout)
{
    if (timeout >= 0 && timeout < TIMEOUTS) {
        const int  state = __sync_or_and_fetch(&timeout_state[timeout], 0);

        /* Refers to an unused timeout? */
        if (!(state & TIMEOUT_USED))
            return -1;

        /* Not armed? */
        if (!(state & TIMEOUT_ARMED))
            return -1;

        /* Return 1 if timeout passed, 0 otherwise. */
        return (state & TIMEOUT_PASSED) ? 1 : 0;

    } else {
        /* Invalid timeout number. */
        return -1;
    }
}

/* Release the timeout.
 * Returns 0 if the timeout had not fired yet, 1 if it had.
*/
static inline int timeout_unset(const int timeout)
{
    if (timeout >= 0 && timeout < TIMEOUTS) {
        /* Obtain the current timeout state to 'state',
         * then clear all but the TIMEOUT_PASSED flag
         * for the specified timeout.
         * Thanks to Bylos for catching this bug. */
        const int  state = _sync_fetch_and_and(&timeout_state[timeout], TIMEOUT_PASSED);

        /* Invalid timeout? */
        if (!(state & TIMEOUT_USED))
            return -1;

        /* Not armed? */
        if (!(state & TIMEOUT_ARMED))
            return -1;

        /* Return 1 if passed, 0 otherwise. */
        return (state & TIMEOUT_PASSED) ? 1 : 0;

    } else {
        /* Invalid timeout number. */
        return -1;
    }
}


int timeout_set(const double seconds)
{
    struct timespec   now, then;
    struct itimerspec when;
    double            next;
    int               timeout, i;

    /* Timeout must be in the future. */
    if (seconds <= 0.0)
        return -1;

    /* Get current time, */
    if (clock_gettime(CLOCK_REALTIME, &now))
        return -1;

    /* and calculate when the timeout should fire. */
    then = now;
    timespec_add(&then, seconds);

    /* Find an unused timeout. */
    for (timeout = 0; timeout < TIMEOUTS; timeout++)
        if (!(__sync_fetch_and_or(&timeout_state[timeout], TIMEOUT_USED) & TIMEOUT_USED))
            break;

    /* No unused timeouts? */
    if (timeout >= TIMEOUTS)
        return -1;

    /* Clear all but TIMEOUT_USED from the state, */
    __sync_and_and_fetch(&timeout_state[timeout], TIMEOUT_USED);

    /* update the timeout details, */
    timeout_time[timeout] = then;

    /* and mark the timeout armable. */
    __sync_or_and_fetch(&timeout_state[timeout], TIMEOUT_ARMED);

    /* How long till the next timeout? */
    next = seconds;
    for (i = 0; i < TIMEOUTS; i++)
        if ((__sync_fetch_and_or(&timeout_state[i], 0) & (TIMEOUT_USED | TIMEOUT_ARMED | TIMEOUT_PASSED)) == (TIMEOUT_USED | TIMEOUT_ARMED)) {
            const double secs = timespec_diff(timeout_time[i], now);
            if (secs >= 0.0 && secs < next)
                next = secs;
        }

    /* Calculate duration when to fire the timeout next, */
    timespec_set(&when.it_value, next);
    when.it_interval.tv_sec = 0;
    when.it_interval.tv_nsec = 0L;

    /* and arm the timer. */
    if (timer_settime(timeout_timer, 0, &when, NULL)) {
        /* Failed. */
        __sync_and_and_fetch(&timeout_state[timeout], 0);
        return -1;
    }

    /* Return the timeout number. */
    return timeout;
}


static void timeout_signal_handler(int signum __attribute__((unused)), siginfo_t *info, void *context __attribute__((unused)))
{
    struct timespec   now;
    struct itimerspec when;
    int               saved_errno, i;
    double            next;

    /* Not a timer signal? */
    if (!info || info->si_code != SI_TIMER)
        return;

    /* Save errno; some of the functions used may modify errno. */
    saved_errno = errno;

    if (clock_gettime(CLOCK_REALTIME, &now)) {
        errno = saved_errno;
        return;
    }

    /* Assume no next timeout. */
    next = -1.0;

    /* Check all timeouts that are used and armed, but not passed yet. */
    for (i = 0; i < TIMEOUTS; i++)
        if ((__sync_or_and_fetch(&timeout_state[i], 0) & (TIMEOUT_USED | TIMEOUT_ARMED | TIMEOUT_PASSED)) == (TIMEOUT_USED | TIMEOUT_ARMED)) {
            const double  seconds = timespec_diff(timeout_time[i], now);
            if (seconds <= 0.0) {
                /* timeout [i] fires! */
                __sync_or_and_fetch(&timeout_state[i], TIMEOUT_PASSED);

            } else
            if (next <= 0.0 || seconds < next) {
                /* This is the soonest timeout in the future. */
                next = seconds;
            }
        }

    /* Note: timespec_set() will set the time to zero if next <= 0.0,
     *       which in turn will disarm the timer.
     * The timer is one-shot; it_interval == 0.
    */
    timespec_set(&when.it_value, next);
    when.it_interval.tv_sec = 0;
    when.it_interval.tv_nsec = 0L;
    timer_settime(timeout_timer, 0, &when, NULL);

    /* Restore errno. */
    errno = saved_errno;
}


int timeout_init(void)
{
    struct sigaction  act;
    struct sigevent   evt;
    struct itimerspec arm;

    /* Install timeout_signal_handler. */
    sigemptyset(&act.sa_mask);
    act.sa_sigaction = timeout_signal_handler;
    act.sa_flags = SA_SIGINFO;
    if (sigaction(TIMEOUT_SIGNAL, &act, NULL))
        return errno;

    /* Create a timer that will signal to timeout_signal_handler. */
    evt.sigev_notify = SIGEV_SIGNAL;
    evt.sigev_signo = TIMEOUT_SIGNAL;
    evt.sigev_value.sival_ptr = NULL;
    if (timer_create(CLOCK_REALTIME, &evt, &timeout_timer))
        return errno;

    /* Disarm the timeout timer (for now). */
    arm.it_value.tv_sec = 0;
    arm.it_value.tv_nsec = 0L;
    arm.it_interval.tv_sec = 0;
    arm.it_interval.tv_nsec = 0L;
    if (timer_settime(timeout_timer, 0, &arm, NULL))
        return errno;

    return 0;
}

int timeout_done(void)
{
    struct sigaction  act;
    struct itimerspec arm;
    int               errors = 0;

    /* Ignore the timeout signals. */
    sigemptyset(&act.sa_mask);
    act.sa_handler = SIG_IGN;
    if (sigaction(TIMEOUT_SIGNAL, &act, NULL))
        if (!errors) errors = errno;

    /* Disarm any current timeouts. */
    arm.it_value.tv_sec = 0;
    arm.it_value.tv_nsec = 0L;
    arm.it_interval.tv_sec = 0;
    arm.it_interval.tv_nsec = 0;
    if (timer_settime(timeout_timer, 0, &arm, NULL))
        if (!errors) errors = errno;

    /* Destroy the timer itself. */
    if (timer_delete(timeout_timer))
        if (!errors) errors = errno;

    /* If any errors occurred, set errno. */
    if (errors)
        errno = errors;

    /* Return 0 if success, errno otherwise. */
    return errors;
}

记住要包括 RT 库编译,即使用 GCC -W -Wall *源的* .c -lrt -o *二进制时* 进行编译。

Remember to include the rt library when compiling, i.e. use gcc -W -Wall *source*.c -lrt -o *binary* to compile.

的想法是,主程序首先调用 timeout_init()来安装所有必要的处理等等,并且可以调用 timeout_done()退出之前deistall它(或后 A子进程fork() ING)。

The idea is that the main program first calls timeout_init() to install all the necessary handlers et cetera, and may call timeout_done() to deistall it before exiting (or in a child process after fork()ing).

要设置超时,你叫 timeout_set(秒)。返回值是超时描述符。目前,只有你可以检查使用标志 timeout_passed(),但超时信号的传递也中断任何阻塞I / O调用。因此,你可以期望超时中断任何阻塞I / O调用。

To set a timeout, you call timeout_set(seconds). The return value is a timeout descriptor. Currently there is just a flag you can check using timeout_passed(), but the delivery of the timeout signal also interrupts any blocking I/O calls. Thus, you can expect the timeout to interrupt any blocking I/O call.

如果你想做的任何事情超过设定的超时一个标志,你不能​​做到这一点的信号处理程序;请记住,在信号处理程序,你是仅限于异步信号安全功能。身边最简单的方法是在 sigwaitinfo使用一个单独的线程与一个无限循环(),用 TIMEOUT_SIGNAL 信号阻塞在所有其它线程。这样的专用线程保证捕捉信号,但在同一时间,不限于异步信号安全功能。它可以,例如,做更多的工作,甚至使用 pthread_kill()将信号发送到特定线程。 (只要该信号有一个处理程序,即使是一个空的身体,它的交付将中断该线程的阻塞I / O调用)。

If you want to do anything more than set a flag at timeout, you cannot do it in the signal handler; remember, in a signal handler, you're limited to async-signal safe functions. The easiest way around that is to use a separate thread with an endless loop over sigwaitinfo(), with the TIMEOUT_SIGNAL signal blocked in all other threads. That way the dedicated thread is guaranteed to catch the signal, but at the same time, is not limited to async-signal safe functions. It can, for example, do much more work, or even send a signal to a specific thread using pthread_kill(). (As long as that signal has a handler, even one with an empty body, its delivery will interrupt any blocking I/O call in that thread.)

下面是一个简单的例子的main()使用超时。这是愚蠢的,并且依赖于与fgets()不重试(当信号中断),但它似乎工作。

Here is a simple example main() for using the timeouts. It is silly, and relies on fgets() not retrying (when interrupted by a signal), but it seems to work.

#include <string.h>
#include <stdio.h>

int main(void)
{
    char    buffer[1024], *line;
    int t1, t2, warned1;

    if (timeout_init()) {
        fprintf(stderr, "timeout_init(): %s.\n", strerror(errno));
        return 1;
    }

    printf("You have five seconds to type something.\n");
    t1 = timeout_set(2.5); warned1 = 0;
    t2 = timeout_set(5.0);
    line = NULL;

    while (1) {

        if (timeout_passed(t1)) {
            /* Print only the first time we notice. */
            if (!warned1++)
                printf("\nTwo and a half seconds left, buddy.\n");
        }

        if (timeout_passed(t2)) {
            printf("\nAw, just forget it, then.\n");
            break;
        }

        line = fgets(buffer, sizeof buffer, stdin);
        if (line) {
            printf("\nOk, you typed: %s\n", line);
            break;
        }
    }

    /* The two timeouts are no longer needed. */
    timeout_unset(t1);
    timeout_unset(t2);

    /* Note: 'line' is non-NULL if the user did type a line. */

    if (timeout_done()) {
        fprintf(stderr, "timeout_done(): %s.\n", strerror(errno));
        return 1;
    }

    return 0;
}

这篇关于在在C linux的定时器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆