不管是在程序還是執行緒,很多時候我們都會使用一些定時器之類的功能,這裡就定時器在多執行緒的使用說一下。首先在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 多執行緒中定時器的使用
在開發linux mjpg streamer程式的時候,使用signal,奇怪的是程式竟然退出了。後來讀了曹老師的文章,才解決了這個問題。所以收錄到自己的部落格裡。呵呵 2010 10 14 19 47 29 曹忠明 華清遠見嵌入式學院講師 不管是在程序還是執行緒,很多時候我們都會使用一些定時器之類...
qt中定時器和多執行緒的使用
定時器和多執行緒的使用 注意 建立多執行緒需要加上新的執行緒類 1 建立乙個新的執行緒類mythread 標頭檔案.h ifndef mythread h define mythread h include class mythread public qthread endif mythread h...