参考1:https://blog.csdn.net/lee244868149/article/details/38710149
参考2:https://blog.csdn.net/weixin_34228387/article/details/86405426
需求:
在写嵌入式软件的时候,需要用到近乎us级别的定时器来实现扫描电压;逻辑是每nus增加nuv,从而实现扫描电压的过程。除了定时器还用到了信号。
理论资料 POSIX定时器:
查阅参考2
Struct timespec
{
_time_t tv_sec; //赋的值是以s为单位
_syscall_slong_t tv_nsec; //赋的值是以ns为单位
}
Struct itimerspec
{
Struct timespec it_interval; //从使能定时器开始计时的时间
Struct timespec it_value; //如果设定此参数,那么定时器会以设定的参数循环执行
}
timer_create();创建一个新的定时器,放回一个唯一的定时器ID
timer_delete();删除一个已经存在的定时器,删除前先让定时器停止;下面会谈到如何让定时器停止;
timer_settime();设置定时器参数;开始定时器;停止定时器都用的这个函数
timer_gettime();
timer_getoverrun();
实际应用:
int posix_timer_id;
struct itimerspec ts;
ts.it_value.tv_sec = 1; // 1
ts.it_value.tv_ nsec = 0; // 2
ts.it_ interval.tv_sec = 1;// 3
ts.it_ interval.tv_ nsec = 0;// 4
//第1、2来设置第一次定时的时间;第2、3来设置循环定时的时间
timer_settime(posix_timer_id, 0, &ts, 0);// 5
//第5来设置定时器参数,并且开始定时器
ts.it_value.tv_sec = 0; // 6
ts.it_value.tv_ nsec = 0; // 7
ts.it_ interval.tv_sec = 0;// 8
ts.it_ interval.tv_ nsec = 0;// 9
timer_settime(posix_timer_id, 0, &ts, 0);
//第 6、7、8、9都设置为0时,表示停止定时器
timer_delete(posix_timer_id);//10
//第10来删除定时器
理论资料 SIGNAL信号:
查阅参考1
实际应用:
//创建线程前,将signal_mask信号集从信号掩码中移除
sigemptyset(&signal_mask);
sigaddset(&signal_mask, SIGUSR1);
sigaddset(&signal_mask, SIGTERM);
pthread_sigmask(SIG_UNBLOCK, &signal_mask, NULL);
//创建新线程, 服务器初接收函数
pthread_create(&threadID_Sample, NULL, ThreadFunction, NULL);
//创建线程后,屏蔽signal_mask信号集;
sigemptyset(&signal_mask);
sigaddset(&signal_mask, SIGUSR1);
sigaddset(&signal_mask, SIGTERM);
pthread_sigmask(SIG_BLOCK, &signal_mask, NULL);
/************************* ThreadFunction线程函数内*********************************/
//初始化信号参数
act.sa_handler = StartSample_IT;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction(SIGUSR1, &act, NULL);
//用来指定定时器到期时要产生的异步通知
memset(&sev, 0, sizeof(sev));
sev.sigev_signo = SIGUSR1;
sev.sigev_notify = SIGEV_SIGNAL;//SIGEV_SIGNAL(产生信号) SIGEV_NONE(不处理) SIGEV_THREAD(新线程处理)SIGEV_THREAD_ID(指定线程处理)
//创建定时器
timer_create(CLOCK_REALTIME, &sev, &posix_timer_id);
//设置定时器并启动
ts.it_value.tv_sec = ns / 1000000000;
ts.it_value.tv_nsec = ns % 1000000000;
printf("ts.it_value.tv_sec:%d\n", ts.it_value.tv_sec);
printf("ts.it_value.tv_nsec:%d\n", ts.it_value.tv_nsec);
timer_settime(posix_timer_id, 0, &ts, 0);
ts.it_value.tv_sec = 0;
ts.it_value.tv_nsec = 0;
timer_settime(posix_timer_id, 0, &ts, 0);//定时器停止
timer_delete(posix_timer_id);//删除定时器
pthread_cancel(threadID_Sample);
pthread_join(threadID_Sample, NULL);//回收线程
在整个过程中遇到的问题包括:
- 信号产生后会传给每个线程,若想只让子线程接收信号,那么就要在父线程中屏蔽该信号。
- 在父线程中创建子线程时候,子线程会继承父线程屏蔽的信号,所以在创建线程前要移除被屏蔽的信号。
- 不用定时器或者线程了,就要删除和销毁线程