參考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);//回收線程
在整個過程中遇到的問題包括:
- 信號產生後會傳給每個線程,若想只讓子線程接收信號,那麼就要在父線程中屏蔽該信號。
- 在父線程中創建子線程時候,子線程會繼承父線程屏蔽的信號,所以在創建線程前要移除被屏蔽的信號。
- 不用定時器或者線程了,就要刪除和銷燬線程