在開發linux mjpg-streamer程式的時候,使用signal,奇怪的是程式竟然退出了。後來讀了曹老師的文章,才解決了這個問題。
所以收錄到自己的部落格裡。呵呵
2010-10-14 19:47:29
——曹忠明 華清遠見嵌入式學院講師
不管是在程序還是執行緒,很多時候我們都會使用一些定時器之類的功能,這裡就定時器在多執行緒的使用說一下。首先在
linux
程式設計中定時器函式有
alarm()
和setitimer(),alarm()
可以提供乙個基於秒的定時功能,而
setitimer
可以提供乙個基於微妙的定時功能。
alarm()
原型:
#include
unsigned int alarm(unsigned int seconds);
這個函式在使用上很簡單,第一次呼叫這個函式的時候是設定定時器的初值,下一次呼叫是重新設定這個值,並會返回上一次定時的剩餘時間。
setitimer()
原型:
#include
int setitimer(int which, const struct itimerval *value,
struct itimerval *ovalue);
這個函式使用起來稍微有點說法,首先是第乙個引數
which
的值,這個引數設定
timer
的計時策略,
which
有三種狀態分別是:
itimer_real:
使用系統時間來計數,時間為
0時發出
sigalrm
訊號,這種定時能夠得到乙個精準的定時,當然這個定時是相對的,因為到了微秒級別我們的處理器本身就不夠精確。
itimer_virtual:
使用程序時間也就是程序分配到的時間片的時間來計數,時間為
0是發出
sigvtalrm
訊號,這種定時顯然不夠準確,因為系統給程序分配時間片不由我們控制。
itimer_prof:
上面兩種情況都能夠觸發
第二個引數引數
value
涉及到兩個結構體:
struct itimerval ;
struct timeval ;
在結構體
itimerval
中it_value
是定時器當前的值,
it_interval
是當it_value的為0
後重新填充的值。而
timeval
結構體中的兩個變數就簡單了乙個是秒乙個是微秒。
上面是這兩個定時函式的說明,這個函式使用本不是很難,可以說是很簡單,但是碰到具體的應用的時候可能就遇到問題了,在多程序程式設計中使用一般不會碰到什麼問題,這裡說的這些問題主要體現在多執行緒程式設計中。比如下面這個程式
#include
#include
#include
#include
#include
#include
void sig_handler(int signo)
void *pthread_func()
}int main(int argc, char **argv)
while(1)
return 0;
}這個程式的理想結果是:
main thread
alarm signal
alarm signal
alarm signal
alarm signal
alarm signal
main thread
可事實上並不是這樣的,它的結果是:
main pthread
alarm signal
main pthread
alarm signal
main pthread
為什麼會出現這種情況呢?是因為傳送給工作執行緒的訊號中斷的主線程的
sleep
,並且這個中情況只影響主線程而不會影響到其他的工作執行緒。我們怎麼才能解決這種問題呢,最簡單的方法是修改這個程式,修改這個執行緒主線程使用
alarm
,工作執行緒使用
sleep
。這樣就能夠達到我們的要求,但是有時候有不能簡單的這樣操作。所以我們就需要進一步的修改我們的程式。在這裡我第乙個想到的是使用
signal(sigalrm, sig_ign),
可是這個是設定整個程序對這個訊號的響應方式,經過測試也確實不能完成我期望的功能,那麼怎麼辦呢
?有這樣乙個函式
pthread_sigmask
,執行緒中的訊號遮蔽,函式的原型及相關函式為:
#include
int pthread_sigmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);
函式中第乙個引數
how有三個值
sig_block
、sig_setmask
和sig_unblock
這裡我們是用第二個值
sig_setmask
int sigemptyset(sigset_t *set);/*
清除訊號集合
set*/
int sigaddset(sigset_t *set, int signum); /*
新增訊號
signum
到訊號集
set中
*/然後我們改造我們的程式為:
#include
#include
#include
#include
#include
#include
void sig_handler(int signo)
void *pthread_func()
}int main(int argc, char **argv)
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, sigalrm);
pthread_sigmask(sig_setmask,&sigset,null);
while(1)
return 0;
}這個時候我們就能夠看到我們想要的結果了。
這裡再附乙個
setitimer
的使用範例
#include
#include
#include
#include
#include
#include
struct itimerval timerval;
void sig_handler(int signo)
void *pthread_func()
}int main(int argc, char **argv)
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, sigalrm);
pthread_sigmask(sig_setmask,&sigset,null);
while(1)
return 0;
}個人的一些理解,有問題希望和大家交流!
多執行緒中定時器的使用
曹忠明 華清遠見嵌入式學院講師 不管是在程序還是執行緒,很多時候我們都會使用一些定時器之類的功能,這裡就定時器在多執行緒的使用說一下。首先在 linux 程式設計中定時器函式有 alarm 和setitimer alarm 可以提供乙個基於秒的定時功能,而 setitimer 可以提供乙個基於微妙的...
多執行緒中定時器的使用
不管是在程序還是執行緒,很多時候我們都會使用一些定時器之類的功能,這裡就定時器在多執行緒的使用說一下。首先在linux程式設計中定時器函式有alarm 和setitimer alarm 可以提供乙個基於秒的定時功能,而setitimer可以提供乙個基於微妙的定時功能。alarm 原型 include...
qt中定時器和多執行緒的使用
定時器和多執行緒的使用 注意 建立多執行緒需要加上新的執行緒類 1 建立乙個新的執行緒類mythread 標頭檔案.h ifndef mythread h define mythread h include class mythread public qthread endif mythread h...