linux定时中断的三种实现

三种定时中断实现:

  1. setitimer 函数产生SIGALRM信号,同时使用signal函数注册
  2. 使用 timer_create + timer_settime 函数可以指定产生任意信号,同时使用signal函数注册
  3. 使用 timer_create + timer_settime 函数 通知线程

得到两个结论:

  1. 结论一:默认情况下,信号将由主进程接收处理,就算信号处理函数是由子线程注册的。
  2. 结论二:对信号的处理(初始化信号函数vTimerInit不论是在主线程中还是子线程中注册,都是一样的)是进程中所有的线程共享的。
  3.  

这篇文章写的比较好,可以直接参考:

https://blog.csdn.net/u014530704/article/details/81415153

//timer_test.c

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



// return: 自CPU上电以来的时间,单位:毫秒
unsigned long long GetCpuRunTimeMs(void)
{
    unsigned long long  uptime = 0;
    struct timespec on;
    if(clock_gettime(CLOCK_MONOTONIC, &on) == 0)
    {
        uptime = on.tv_sec * 1000ul;
        uptime += on.tv_nsec / 1000000ul;
    }

    return uptime;
}
//信号处理函数
void signal_func(int signo)
{
    static unsigned long long start_time = 0;

    switch(signo)
    {
        case SIGALRM:
            printf("%s:1s-----> take %llu ms,signo=SIGALRM(%d)\n",__FUNCTION__,GetCpuRunTimeMs()-start_time,signo);
            break;
        case SIGUSR1:
            printf("%s:1s-----> take %llu ms,signo=SIGUSR1(%d)\n",__FUNCTION__,GetCpuRunTimeMs()-start_time,signo);
            break;
        default:
			printf("unknown signal : %d\n",signo);
            break;
    }
    start_time = GetCpuRunTimeMs();
}
//setitimer函数相关初始化
void vTimerInit(void)
{
    struct itimerval value, old_value;

    signal(SIGALRM, signal_func);
    value.it_value.tv_sec = 1; //设置距离首次中断的时间
    value.it_value.tv_usec = 0;
    value.it_interval.tv_sec = 1; //时间间隔
    value.it_interval.tv_usec = 0;
    setitimer(ITIMER_REAL, &value, &old_value);    
}
//timer_create初始化相关,注册信号SIGUSR1
int vTimerCreateInit(void)
{
    struct sigevent evp;
    struct itimerspec ts;
    timer_t timer;
    int ret;
    memset(&evp, 0, sizeof(struct sigevent));   //清零初始化
    evp.sigev_value.sival_ptr = &timer;
    evp.sigev_notify = SIGEV_SIGNAL; //信号通知的方式
    evp.sigev_signo = SIGUSR1;		//触发后用SIGUSR1信号通知(主线程)
    signal(SIGUSR1, signal_func); 	//注册SIGUSR1的响应函数(主线程接收到该信号会回调该函数)

    ret = timer_create(CLOCK_REALTIME, &evp, &timer);
    if( ret )
        perror("timer_create");

    ts.it_interval.tv_sec = 1;
    ts.it_interval.tv_nsec = 0;
    ts.it_value.tv_sec = 1;
    ts.it_value.tv_nsec = 0;

    ret = timer_settime(timer, 0, &ts, NULL);
    if( ret )
        perror("timer_settime");

    return ret;
}

void timer_thread(union sigval v)
{
    static unsigned long long start_time = 0;

    printf("%s:1s-----> take %llu ms, v.sival_int = %d\n",__FUNCTION__,GetCpuRunTimeMs()-start_time,v.sival_int);
    start_time = GetCpuRunTimeMs();

}
//不采用信号通知的方式,直接通知线程
int vTimerPthreadInit(void)
{
    timer_t timerid;
    struct sigevent evp;
    int ret;
    memset(&evp, 0, sizeof(struct sigevent));   //清零初始化

    evp.sigev_value.sival_int = 1111;       
    evp.sigev_notify = SIGEV_THREAD;        	//线程通知的方式,派驻新线程,触发后直接调用该线程(这样不会干扰到主线程的sleep了)
    evp.sigev_notify_function = timer_thread;   //线程函数地址

    ret = timer_create(CLOCK_REALTIME, &evp, &timerid);
    if( ret )
        perror("timer_create");

    struct itimerspec it;
    it.it_interval.tv_sec = 1;  //间隔1s
    it.it_interval.tv_nsec = 0;
    it.it_value.tv_sec = 1;     
    it.it_value.tv_nsec = 0;

    ret = timer_settime(timerid, 0, &it, NULL);
    if( ret )
        perror("timer_settime");

    return ret;

}

//线程,用于测试信号接收
void *vTimerProc(void *arg)
{
    printf("pthread func:%s\n",__FUNCTION__);

    unsigned long long start_time = 0;
    while(1)
    {
        start_time = GetCpuRunTimeMs();
        sleep(5);
        printf("%s:sleep 5s take %llu ms\n",__FUNCTION__,GetCpuRunTimeMs()-start_time);
    }    
    return NULL;

}
//线程,用于测试信号接收
void *vSleepProc(void *arg)
{
    printf("pthread func:%s\n",__FUNCTION__);

    unsigned long long start_time = 0;
    while(1)
    {
        start_time = GetCpuRunTimeMs();
        sleep(5);
        printf("%s:sleep 5s take %llu ms\n",__FUNCTION__,GetCpuRunTimeMs()-start_time);
    }    
    return NULL;

}

//线程初始化函数
void  vPthreadInit(void)
{
    printf("func:%s\n",__FUNCTION__);

    pthread_t timer_thread_id = 0;
    pthread_create(&timer_thread_id, NULL, vTimerProc, NULL);

    pthread_t sleep_thread_id = 0;
    pthread_create(&sleep_thread_id, NULL, vSleepProc, NULL);

}


int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("please input eg: %s 1|2|3\n",argv[0]);
        printf("1:user SIGALRM\n");
        printf("2:user SIGUSR1\n");
        printf("3:user thread\n");
        return -1;
    }
    printf("func:%s ,process id is %d\n",__FUNCTION__,getpid());
    struct itimerval value, old_value;
    unsigned long long start_time = 0;
    unsigned long long end_time = 0;

    int ctrl = atoi(argv[1]);
    switch(ctrl)
    {
        case 1:
            vTimerInit();
            break;
        case 2:
            vTimerCreateInit();
            break;
        case 3:
            vTimerPthreadInit();
            break;
        default:
            return -1;
            break;
    }

    vPthreadInit();

    while(1)
    {
        start_time = GetCpuRunTimeMs();
        sleep(5);
        printf("%s:sleep 5s take %llu ms\n",__FUNCTION__,GetCpuRunTimeMs()-start_time);
    }

	printf("man thread exit\n");
}


 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值