首页 > 其他分享 >alarm和setitimer

alarm和setitimer

时间:2023-03-05 14:34:25浏览次数:34  
标签:定时器 int setitimer alarm value 信号 include

Linux提供了alarm系统调用和SIGALRM信号。

alarm系统调用

unsigned int alarm(unsigned int seconds);

​ - 功能:设置定时器(闹钟)。函数调用,开始倒计时,当倒计时为0的时候,函数会给当前的进程发送一个信号:SIGALARM

​ - 参数:

​ seconds: 倒计时的时长,单位:秒。如果参数为0,定时器无效(不进行倒计时,不发信号)。

​ 取消一个定时器,通过alarm(0)。

​ - 返回值:

​ - 之前没有定时器,返回0

​ - 之前有定时器,返回之前的定时器剩余的时间

例如:

​ alarm(10); -> 返回0

​ 过了1秒

​ alarm(5); -> 返回9

SIGALARM :默认终止当前的进程,每一个进程都有且只有唯一的一个定时器。

新手实例

注意 :alarm函数不阻塞程序,即与进程的状态无关(自然定时法)

#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>

int main()
{
    int seconds = alarm(5);
    printf("seconds = %d\n", seconds); // 0

    sleep(2);                          // 意味着不阻塞闹钟
    seconds = alarm(2);                // 不阻塞,就是指睡眠之后立马执行下面的打印
    printf("seconds = %d\n", seconds); // 3

    while (1)
    {
    }

    return 0;
}

小的案例:计算机1秒可以数数多少?

我们将每个数打印输出在终端时,由于终端也有缓存,需要耗费磁盘io的时间,所以当我们在屏幕上观察时程序可能运行了不止1秒。计算机数数是考虑计算机内核数数的时间,可以考虑重定向,>>,这样只操作了一次。同时切换内核和用户区也都会造成时间损耗。
实际的时间 = 内核时间 + 用户时间 + 消耗的时间
进行文件IO操作的时候比较浪费时间。

setitimer 定时器

使用定时器,要安装SIGALRM信号。假设不安装SIGALRM信号,则进程收到SIGALRM信号后。缺省的动作就是终止当前进程。

int setitimer(int which, const struct itimerval *new_value,

​ struct itimerval *old_value);

​ - 功能:设置定时器(闹钟)。精度微妙us,可以实现周期性定时

​ - 参数:

​ - which : 定时器以什么时间计时

​ ITIMER_REAL: 真实时间,时间到达,发送 SIGALRM 常用

​ ITIMER_VIRTUAL: 用户时间,时间到达,发送 SIGVTALRM

​ ITIMER_PROF: 以该进程在用户态和内核态下所消耗的时间来计算,时间到达,发送 SIGPROF

​ - new_value: 设置定时器的属性

​ struct itimerval { // 定时器的结构体

​ struct timeval it_interval; // 每个阶段的时间,间隔时间

​ struct timeval it_value; // 延迟多长时间执行定时器

​ };

​ struct timeval { // 时间的结构体

​ time_t tv_sec; // 秒数

​ suseconds_t tv_usec; // 微秒

​ };

​ - old_value :记录上一次的定时的时间参数,一般不使用,指定NULL

​ - 返回值:

​ 成功 0

​ 失败 -1 并设置错误号

信号捕捉

typedef void (*sighandler_t)(int);

​ sighandler_t signal(int signum, sighandler_t handler);

​ - 功能:设置某个信号的捕捉行为

​ - 参数:

​ - signum: 要捕捉的信号

​ - handler: 捕捉到信号要如何处理

​ - SIG_IGN : 忽略信号

​ - SIG_DFL : 使用信号默认的行为

​ - 回调函数 : 这个函数是内核调用,程序员只负责写,捕捉到信号后如何去处理信号。

​ 回调函数:

​ - 需要程序员实现,提前准备好的,函数的类型根据实际需求,看函数指针的定义

​ - 不是程序员调用,而是当信号产生,由内核调用

​ - 函数指针是实现回调的手段,函数实现之后,将函数名放到函数指针的位置就可以了。

​ - 返回值:

​ 成功,返回上一次注册的信号处理函数的地址。第一次调用返回NULL

​ 失败,返回SIG_ERR,设置错误号

SIGKILL SIGSTOP不能被捕捉,不能被忽略。

新手案例

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

// 回调函数
void myalarm(int num)
{
    printf("捕捉到了信号的编号是:%d\n", num);
    printf("xxxxx\n");
}

// 3秒过后,每隔两秒定时一次
int main()
{
    // 注册信号捕捉,要放在设置定时器之前
    // signal(SIGALRM, SIG_IGN);
    // signal(SIGALRM, SIG_DFL);
    // void (*sighandler_t)(int); 函数指针,int类型的参数表示捕捉到的信号的值。

    signal(SIGALRM, myalarm);
    struct itimerval new_value; // 分配在栈空间,会随机赋值

    // 设置间隔时间
    new_value.it_interval.tv_sec = 2;
    new_value.it_interval.tv_usec = 0;

    // 设置延迟时间,3秒之后开始第一次定时
    new_value.it_value.tv_sec = 3;
    new_value.it_value.tv_usec = 0; // 毫秒数需要设置,否则默认随机值

    int ret = setitimer(ITIMER_REAL, &new_value, NULL); // 非阻塞
    printf("定时器开始了...\n");

    if (ret == -1)
    {
        perror("setitimer");
        exit(0);
    }

    getchar();

    return 0;
}

程序结果:

标签:定时器,int,setitimer,alarm,value,信号,include
From: https://www.cnblogs.com/hereskiki/p/17180510.html

相关文章

  • QT debug/moc_frmalarminfo.o:(.data.rel.ro._ZTV12FrmAlarmInfo[_ZTV12FrmAlarmInfo]
    这个报错很具有迷惑性,,,我在网上还看见了ZTI12的报错,但是仔细一看发现是.o文件报错。简单解释下.o文件(此解释来自百度):o就是object,也就相当于windows下编译的obj文件,俗......
  • linux下定时器的使用 -- alarm() & setitimer()
    Linux下的定时器有两种,以下分别介绍:1、alarm-------------------------------------------   如果不要求很精确的话,用alarm()和signal()就够了   unsignedi......
  • P7060 [NWRRC2014]Alarm Clock
    Alicelikesherdigitalalarmclock.Shesetsthemupeveryevening.LastnightAlicehadadreamaboutherclock.Unfortunately,theonlythingsheisablet......
  • SCHEDULE_EXACT_ALARM权限在android12.0崩溃的问题
    问题重现简单讲,就是以Android12为目标平台的App,如果使用到了AlarmManager来设置定时任务,并且设置的是精准的闹钟(使用了setAlarmClock()、setExact()、setExactAndAllowW......
  • android之定时器AlarmManager .
     果图:      当我们点击定时时,会弹出一个时间选择器,选定好时间之后,系统便可以进行定时了。注意,这里可不是会真的响铃,我们在定时的任务里并没有......
  • Android AlarmManager
    publicclassMainActivityextendsAppCompatActivity{privatestaticfinalintNOTIFICATION_ID=0;AlarmManageralarmManager;IntentAlarmReceive......