linux时钟中断分析

94 阅读2分钟

linux时钟中断分析

前置知识

linux内部有三个内置定时器

  1. ITIMER_REAL:实时定时器,不管进程在何种模式下运行(甚至在进程被挂起时),它总在计数。定时到达,向进程发送SIGALRM信号。

  2. ITIMER_VIRTUAL:这个不是实时定时器,当进程在用户模式(即程序执行时)计算进程执行的时间。定时到达后向该进程发送SIGVTALRM信号。 

  3. ITIMER_PROF:进程在用户模式(即程序执行时)和核心模式(即进程调度用时)均计数。定时到达产生SIGPROF信号。ITIMER_PROF记录的时间比ITIMER_VIRTUAL多了进程调度所花的时间。

根据定时器编写程序

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

static void sig_handler(int signo);
int lastsec, countsec;
int main(void)
{
    struct itimerval v;
    long nowsec, nowusec;
    // C 库函数 void(*signal(int sig, void (*func)(int)))(int)
    // 设置一个函数来处理信号,即带有 sig 参数的信号处理程序。
    // SIGUSR1 用户自定义信号 默认处理:进程终止
    if (signal(SIGUSR1, sig_handler) == SIG_ERR)
    {
        printf("create SIGUSR.fail\n");
        exit(0);
    }
    if (signal(SIGALRM, sig_handler) == SIG_ERR)
    {
        printf("create sigalrm fail\n");
        exit(0);
    }
    printf("I AN RUNNING PID IS %d\n", getpid());
    v.it_interval.tv_sec = 9;
    v.it_interval.tv_usec = 999999;
    v.it_value.tv_sec = 9;
    v.it_value.tv_usec = 999999;

    setitimer(ITIMER_REAL, &v, NULL);
    // 设置定时器
    lastsec = v.it_value.tv_sec;
    countsec = 0;
    while (1)
    {
        getitimer(ITIMER_REAL, &v);
        nowsec = v.it_value.tv_sec;
        nowusec = v.it_value.tv_usec;
        if (nowsec == lastsec - 1)
        {
            raise(SIGUSR1);
            lastsec = nowsec;
            countsec++;
        }
    }
}
// 定时执行的函数
static void sig_handler(int signo)
{
    switch (signo)
    {
    case SIGUSR1:
        printf("one sec passed\n");
        break;
    case SIGALRM:
    {
        printf("TIMER HAS BEEN ZERO ELAPSED %D SEC\n", countsec);
        lastsec = countsec;
        countsec = 0;
        break;
    }
    default:
        break;
    }
}

运行结果

定时器运行中

20230328111059.png

kill进程后: 20230328111106.png

总结

定时器能够定时的执行一个任务,通过实现sighandler函数。并且在定时器运行过程中还可以受命令控制。

结语

本次的文章到这里就结束啦!♥♥♥读者大大们认为写的不错的话点个赞再走哦 ♥♥♥

每天一个知识点,每天都在进步!♥♥