Linux setitimer參數設定如何使用程式

來源:互聯網
上載者:User

轉載自:http://www.cublog.cn/u2/76349/showart_2227666.html

 

Linux setitimer對於電腦使用的玩家的常用軟體,然後我就學習及深入的研究Linux
setitimer,在這裡和大家一起探討Linux setitimer的使用方法,希望對大家有用。Linux
setitimer()為Linux的API,並非C語言的Standard Library,Linux
setitimer()有兩個功能,一是指定一段時間後,才執行某個function,二是每間格一段時間就執行某個function,以下程式demo
如何使用Linux setitimer()。

 
  1. view plaincopy to clipboardprint?/*    
  2. Filename    : timer.cpp    
  3. Compiler    : gcc 4.1.0 on Fedora Core 5    
  4. Description : Linux setitimer() set the interval to run function    
  5. Synopsis    : #include <sys/time.h>    
  6. int Linux setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);    
  7. struct itimerval {    
  8. struct timerval it_interval;    
  9. struct timerval it_value;    
  10. };    
  11. struct timeval {    
  12. long tv_sec;    
  13. long tv_usec;    
  14. }  
  15. Release     : 11/25/2006    
  16. */     
  17. #include <stdio.h>    // for printf()     
  18. #include <unistd.h>   // for pause()     
  19. #include <signal.h>   // for signal()     
  20. #include <string.h>   // for memset()     
  21. #include <sys/time.h> // struct itimeral. Linux setitimer()     
  22. void printMsg(int);     
  23. int main() {     
  24. // Get system call result to determine successful or failed     
  25. int res = 0;     
  26. // Register printMsg to SIGALRM     
  27. signal(SIGALRM, printMsg);     
  28. struct itimerval tick;     
  29. // Initialize struct     
  30. memset(&tick, 0, sizeof(tick));     
  31. // Timeout to run function first time     
  32. tick.it_value.tv_sec = 1;  // sec     
  33. tick.it_value.tv_usec = 0; // micro sec.     
  34. // Interval time to run function     
  35. tick.it_interval.tv_sec = 1;     
  36. tick.it_interval.tv_usec = 0;     
  37. // Set timer, ITIMER_REAL : real-time to decrease timer,     
  38. //            send SIGALRM when timeout     
  39. res = Linux setitimer(ITIMER_REAL, &tick, NULL);     
  40. if (res) {     
  41. printf("Set timer failed!!/n");     
  42. }     
  43. // Always sleep to catch SIGALRM signal     
  44. while(1) {     
  45. pause();     
  46. }     
  47. return 0;       
  48. }     
  49. void printMsg(int num) {     
  50. printf("%s","Hello World!!/n");     
  51. }     
  52.  

當Linux setitimer()所執行的timer時間到了,會呼叫SIGALRM
signal,所以在第30行用signal()將要執行的function指定給SIGALRM。 在第43行呼叫Linux
setitimer()設定timer,但Linux setitimer()

第二個參數是sturct,負責設定timeout時間,所以第36行到第
40行設定此struct。itimerval.it_value設定第一次執行function所延遲的秒數,
itimerval.it_interval設定以後每幾秒執行function,所以若只想延遲一段時間執行function,只要設定
itimerval.it_value即可.

若要設定間格一段時間就執行function,則it_value和it_interval都要設定,否則
funtion的第一次無法執行,就別說以後的間隔執行了。 第36行和第39行的tv_sec為sec,第37行和40行為micro
sec(0.001 sec)。
第43行的第一個參數ITIMER_REAL,表示以real-time方式減少timer,在timeout時會送出SIGALRM signal。

第三個參數會存放舊的timeout值,如果不需要的話,指定NULL即可。 第47
行的pause(),命令系統進入sleep狀態,等待任何signal,一定要用while(1)無窮迴圈執行pause(),如此才能一直接收
SIGALRM signal以間隔執行function,若拿掉while(1),則function只會執行一次而已。

 

三,樣本程式

執行個體一:訊號發送及處理,看看函數sigaction是怎麼使用的。
CODE

#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
void user_func(int,siginfo_t*,void*);

int main(int argc,char**argv)
{
struct sigaction act;
int sig;
sig=atoi(argv[1]);

sigemptyset(&act.sa_mask);
act.sa_flags=SA_SIGINFO;
act.sa_sigaction=(void * )user_func;

if(sigaction(sig,&act,NULL) < 0)
{
printf("install sigal error/n");
}

while(1)
{
sleep(2);
printf("wait for the signal/n");
}
}
void user_func(int signum,siginfo_t *info,void *myact)
{
printf("receive signal %d/n/n/n", signum);
sleep(5);
}

在一終端執行cc -o act act.c
$./act 8&
[1] 992
$ wait for the signal
$

在另一終端執行

#kill -s 8 992

看看。。

$receive signal 8

執行個體二:訊號阻塞及訊號集操作

CODE

#include <signal.h>
#include <unistd.h>
void user_func(int);
main()
{
sigset_t new_mask,old_mask,pending_mask;
struct sigaction act;

sigemptyset(&act.sa_mask);
act.sa_flags=SA_SIGINFO;
act.sa_sigaction=(void*)user_func;

if(sigaction(SIGRTMIN+10,&act,NULL))
printf("install signal SIGRTMIN+10 error/n");

sigemptyset(&new_mask);
sigaddset(&new_mask,SIGRTMIN+10);

if(sigprocmask(SIG_BLOCK, &new_mask,&old_mask))
printf("block signal SIGRTMIN+10 error/n");

sleep(20);

printf("/n/nNow begin to get pending mask and unblock SIGRTMIN+10/n/n");
if(sigpending(&pending_mask)<0)
printf("get pending mask error/n");
if(sigismember(&pending_mask,SIGRTMIN+10))
printf("signal SIGRTMIN+10 is pending/n");

if(sigprocmask(SIG_SETMASK,&old_mask,NULL)<0)
printf("unblock signal error/n");

printf("signal unblocked ,ok ... .../n/n/n");
}
void user_func(int signum)
{
printf("receive signal %d /n",signum);
}

$cc -o sus sus.c
$./sus&
[1] 997

another console
#kill -s 42 pid

看看...

$
Now begin to get pending mask and unblock SIGRTMIN+10

signal SIGRTMIN+10 is pending
receive signal 42
signal unblocked ,ok ... ...

[1]+ Exit 31 ./d
$

執行個體三:signal例子

CODE

#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#define damo
void user_func(int no)
{
switch (no)
{
case 1:
printf("Get SIGHUP./n");
break;
case 2:
printf("Get SIGINT/n");
break;
case 3:
printf("Get SIGQUIT /n");
break;
default:
printf("What wan yi a /n/n");
break;
}

}
int main()
{
printf("rocess id is %d/n ",getpid());

#ifdef damo
signal(SIGHUP, user_func);
signal(SIGINT, user_func);
signal(SIGQUIT, user_func);
signal(SIGBUS, user_func);
#else
signal(SIGHUP, SIG_IGN);
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
signal(SIGBUS, SIG_DFL);
#endif

while(1)
;
}

這個就是signal的用法集中展示,也是我經常用的一個方法。說實話,sco太古老了。。俺只能用這個函數了。
測試時你可以把#define damo這個注釋和不注釋看看。深刻體會signal的用法。

BTW:signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);

等等忽略了這些訊號後,可以讓一個進程終端無關,即使你退出這個tty.當然kill訊號還是不能屏蔽的。
這種方式多在守護進程中採用。

$ cc -o si si.c
$./si

Process id is 1501

在另一個tty上
#ps -ef
bank 1501 1465 51 04:07 pts/0 00:00:13 ./si
bank 1502 800 0 04:08 pts/1 00:00:00 ps -ef
#
注意觀察這時候是1456
你把./si這個tty關掉。
這時候你再
#ps -ef看看
bank 1501 1 50 04:07 ? 00:00:59 ./si
bank 1503 800 0 04:09 pts/1 00:00:00 ps -ef
注意這個1和?,知道這個進程成啥了吧?成精拉。哈哈~~

執行個體四:pause函數
CODE

#include <unistd.h>
#include <stdio.h>
#include <signal.h>
void user_func()
{
printf("/n/nCatch a signal SIGINT /n");
}

int main()
{
printf ("pid = %d /n/n ",getpid());
signal(SIGINT, user_func);
pause();
printf("receive a signal /n/n");
}

在這個例子中,程式開始執行,就象進入了死迴圈一樣,這是因為進程正在等待訊號,
當我們按下Ctrl-C時,訊號被捕捉,並且使得pause退出等待狀態。

執行個體五:下面是關於setitimer調用的一個簡單例子。

CODE

#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/time.h>

void user_func(int sig)
{
if ( sig == SIGALRM)
printf("Catch a signal SIGALRM /n");
else if ( sig == SIGVTALRM)
printf("Catch a signal SIGVTALRM/n");
}

int main()
{
struct itimerval value,ovalue,value2;

printf("rocess id is = %d /n",getpid());

signal(SIGALRM, user_func);
signal(SIGVTALRM, user_func);

value.it_value.tv_sec = 1;
value.it_value.tv_usec = 0;
value.it_interval.tv_sec = 1;
value.it_interval.tv_usec = 0;

setitimer(ITIMER_REAL, &value, &ovalue);

value2.it_value.tv_sec = 1;
value2.it_value.tv_usec = 500000;
value2.it_interval.tv_sec = 1;
value2.it_interval.tv_usec = 500000;

setitimer(ITIMER_VIRTUAL, &value2, &ovalue);

while(1);
}

在該例子中,每隔1秒發出一個SIGALRM,每隔1.5秒發出一個SIGVTALRM訊號:

結果如下
$ ./ti
Process id is = 1734
Catch a signal SIGALRM
Catch a signal SIGVTALRM
Catch a signal SIGALRM
Catch a signal SIGALRM
Catch a signal SIGVTALRM
Catch a signal SIGALRM
Catch a signal SIGVTALRM
Catch a signal SIGALRM
Catch a signal SIGALRM
Catch a signal SIGVTALRM
Catch a signal SIGALRM
Catch a signal SIGVTALRM
Catch a signal SIGALRM
Catch a signal SIGALRM
Catch a signal SIGVTALRM

ctrl+c中斷。
....

開始喜歡setitimer函數了。。。

四,補充

不得不介紹一下setjmp和longjmp的作用。

在用訊號的時候,我們看到多個地方要求進程在檢查收到訊號後,從原來的系統調用中直接返回,而不是等到該調用完成。
這種進程突然改變其內容相關的情況,就是使用setjmp和longjmp的結果。setjmp將儲存的上下文存入使用者區,並繼續在舊的
上下文中執行。這就是說,進程執行一個系統調用,當因為資源或其他原因要去睡眠時,核心為進程作了一次setjmp,如果
在睡眠中被訊號喚醒,進程不能再進入睡眠時,核心為進程調用longjmp,該操作是核心為進程將原先setjmp調用儲存在進程
使用者區的上下文恢複成現在的上下文,這樣就使得進程可以恢複等待資源前的狀態,而且核心為setjmp返回1,使得進程知道
該次系統調用失敗。這就是它們的作用。

有時間再man 一下waitpid吧。。都是很有用的。

五,後記

訊號的處理從以前的使用到最終文檔的成形,每次都感覺挺難,其實是挺偏的。畢竟,訊號我們
一般接觸的少,用的也少。其實大家不要談訊號色變,仔細研究一下,發現很有意思。
我接觸的東西沒有直接用訊號處理一大堆東西的,都是簡單的對訊號的使用,所有例子比較少,很多
例子都是參考網路資料的。很多資料都是參考了網友的資料而成,尤其是鄭彥興網友。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.