多線程中定時器的使用
unsigned int alarm(unsigned int seconds);
這個函數(shù)在使用上很簡單,第一次調(diào)用這個函數(shù)的時候是設置定時器的初值,下一次調(diào)用是重新設置這個值,并會返回上一次定時的剩余時間。
#i nclude
int setitimer(int which, const struct itimerval *value,
這個函數(shù)使用起來稍微有點說法,首先是第一個參數(shù)which的值,這個參數(shù)設置timer的計時策略,which有三種狀態(tài)分別是:
ITIMER_REAL:使用系統(tǒng)時間來計數(shù),時間為0時發(fā)出SIGALRM信號,這種定時能夠得到一個精準的定時,當然這個定時是相對的,因為到了微秒級別我們的處理器本身就不夠精確。
ITIMER_VIRTUAL:使用進程時間也就是進程分配到的時間片的時間來計數(shù),時間為0是發(fā)出SIGVTALRM信號,這種定時顯然不夠準確,因為系統(tǒng)給進程分配時間片不由我們控制。
ITIMER_PROF:上面兩種情況都能夠觸發(fā)
第二個參數(shù)參數(shù)value涉及到兩個結(jié)構體:
struct itimerval {
struct timeval {
};
在結(jié)構體itimerval中it_value是定時器當前的值,it_interval是當it_value的為0后重新填充的值。而timeval結(jié)構體中的兩個變量就簡單了一個是秒一個是微秒。
上面是這兩個定時函數(shù)的說明,這個函數(shù)使用本不是很難,可以說是很簡單,但是碰到具體的應用的時候可能就遇到問題了,在多進程編程中使用一般不會碰到什么問題,這里說的這些問題主要體現(xiàn)在多線程編程中。比如下面這個程序
#i nclude
#i nclude
#i nclude
#i nclude
#i nclude
#i nclude
void sig_handler(int signo)
{
}
void *pthread_func()
{
}
int main(int argc, char **argv)
{
}
這個程序的理想結(jié)果是:
main thread
alarm signal
alarm signal
alarm signal
alarm signal
alarm signal
main thread
可事實上并不是這樣的,它的結(jié)果是:
main pthread
alarm signal
main pthread
alarm signal
main pthread
為什么會出現(xiàn)這種情況呢?是因為發(fā)送給工作線程的信號中斷的主線程的sleep,并且這個中情況只影響主線程而不會影響到其他的工作線程。我們怎么才能解決這種問題呢,最簡單的方法是修改這個程序,修改這個線程主線程使用alarm,工作線程使用sleep。這樣就能夠達到我們的要求,但是有時候有不能簡單的這樣操作。所以我們就需要進一步的修改我們的程序。在這里我第一個想到的是使用signal(SIGALRM, SIG_IGN),可是這個是設置整個進程對這個信號的響應方式,經(jīng)過測試也確實不能完成我期望的功能,那么怎么辦呢?有這樣一個函數(shù)pthread_sigmask,線程中的信號屏蔽,函數(shù)的原型及相關函數(shù)為:
#i nclude
int pthread_sigmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);
函數(shù)中第一個參數(shù)how有三個值SIG_BLOCK、SIG_SETMASK和SIG_UNBLOCK這里我們是用第二個值SIG_SETMASK
int sigemptyset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
然后我們改造我們的程序為:
#i nclude
#i nclude
#i nclude
#i nclude
#i nclude
#i nclude
void sig_handler(int signo)
{
}
void *pthread_func()
{
}
int main(int argc, char **argv)
{
}
這個時候我們就能夠看到我們想要的結(jié)果了。
這里再附一個setitimer的使用范例
#i nclude
#i nclude
#i nclude
#i nclude
#i nclude
#i nclude
struct itimerval timerval;
void sig_handler(int signo)
{
}
void *pthread_func()
{
}
int main(int argc, char **argv)
{
}
評論