三种定时中断实现:
- setitimer 函数产生SIGALRM信号,同时使用signal函数注册
- 使用 timer_create + timer_settime 函数可以指定产生任意信号,同时使用signal函数注册
- 使用 timer_create + timer_settime 函数 通知线程
得到两个结论:
- 结论一:默认情况下,信号将由主进程接收处理,就算信号处理函数是由子线程注册的。
- 结论二:对信号的处理(初始化信号函数
vTimerInit不论是在主线程中还是子线程中注册,都是一样的
)是进程中所有的线程共享的。
这篇文章写的比较好,可以直接参考:
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");
}