linux 多執行緒中定時器的使用

2021-05-24 01:47:08 字數 3680 閱讀 1977

在開發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...