乐趣区

关于linux:linux下的计时器

近来有读者或者会蛊惑,在 linux 下开发时往往会遇到一些场景,例如:如何让程序运行特定的工夫而后退出?如何在循环肯定的工夫后主动执行某段程序,例如在判断到小孩关上游戏,运行 5 分钟后主动执行退出脚本?这就波及到中断和计时器的常识了。

通常在 linux 中咱们能够应用以下两种计时器函数来实现代码

  1. alarm 函数
    所需头文件 #include<unistd.h>
    原型:
    unsigned int alarm(unsigned int seconds)

alarm 函数给发送一个 SIGALRM 中断,由 signal 函数捕获而后解决。
以下是配合 signal 函数

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

int flag = 0;
int main(void)
{
    /*lambda 表达式简略定义一个中断处理函数 */
    auto bb = [](int sig) -> void{printf("alarm!\n"); flag=1; return; };
    signal(SIGALRM, bb);  // 注册捕捉信号的函数,即 交由 bb 解决
    alarm(1);
    while (1)
    {if (flag == 1)
        {printf("hhh\n");
            return 0;
        }
    }
    return 0;
}

【参考:https://linuxhint.com/sigalar…】
下面这个例子中是说,期待 2 秒当前主动完结循环,这一性能的实现。然而 alarm 函数一个过程只能有一个定(计)时器,这对于多线程和异步程序来说特地不敌对,同时应用会有抵触和平安问题。
在 bb 函数里减少 alarm(k)能够实现反复发送的性能。然而每一个 alarm 收回的 SIGALRM 中断调用的都是 bb 函数,在不同的线程里是不会做辨别的。而且只能以秒为单位,局限比拟大。

  1. setitimer()
    setitimer()为 Linux 的 API,并非 C 语言的 Standard Library,setitimer()有两个性能,一是指定一段时间后,才执行某个 function,二是每间格一段时间就执行某个 function,以下程序 demo 如何应用 setitimer()。
    定义:

     #include <sys/time.h>
     int setitimer( int which,
                 const struct itimerval *value,   
                 struct itimerval *ovalue );

    ITIMER_REAL:以零碎实在的工夫来计算,它送出 SIGALRM 信号。
    ITIMER_VIRTUAL:以该过程在用户态下破费的工夫来计算,它送出 SIGVTALRM 信号。
    ITIMER_PROF:以该过程在用户态下和内核态下所费的工夫来计算,它送出 SIGPROF 信号。

上面是实例

#include <sys/time.h>
#include <signal.h>
#include <stdio.h>

int main(void)
{auto bb = [](int signum) -> void{printf("alarm!\n"); return;};
    signal(SIGALRM, bb);
    struct itimerval new_one, old_one; 
    /*******  通过 new_one 设置 **********/
    /* tv_sec + tv_usec* 1/1e6 = 反复的间隔时间 it_interval 为 0 时候则始终延时 */ 
    new_one.it_interval.tv_sec = 0; 
    new_one.it_interval.tv_usec = 3e5;  // 取值 < 1e6
     /* 同理,初始执行工夫 */
    new_one.it_value.tv_sec = 1;
    new_one.it_value.tv_usec = 0; // 取值 < 1e6

    setitimer(ITIMER_REAL, &new_one, &old_one); // old_one 不必赋值
    
    for(;;);
    printf("1122\n");
    return 0;
}

后记:有其余实现形式吗,有没有什么注意事项?底层原理是什么?当前有机会持续开掘。

退出移动版