數據結構
- 定時器結構:
struct itimerval
{
struct timerval it_value;//Interval for periodic timer,從設置定時器開始到第一次定時器生效的時間
struct timerval it_interval;//Time until next expiration,定時器生效的時間間隔
}
① 若
it_value=0
,系統將無視it_interval
並終止定時器,因此可利用這一特性disable定時器
② 若it_interval=0
,則定時器執行一次後失效
- 時間存儲結構:
struct timeval { time_t tv_sec;//秒 suseconds_t tv_usec;//微秒(microseconds) }
定時器類型
-
ITIMER_REAL
:0,自然定時,計算自然時間,實時衰減;當此計時器到期時,將發送SIGALRM信號。 -
ITIMER_VIRTUAL
:1,虛擬空間計時(用戶空間),只計算進程佔用cpu的時間,進程虛擬時間中的衰減;它只在進程執行時運行;SIGVTALRM信號在到期時發送。 -
ITIMER_PROF
,2,運行時計時(用戶+內核),計算佔用cpu及執行系統調用的時間,進程虛擬時間和系統代表進程運行時的衰減;它被設計用於解釋程序執行的統計分析;每次ITIMER_PROF計時器到期時,都會傳遞SIGPROF信號。
方法
-
獲取系統時間(毫秒級)
注意,獲得的數據從1970.01.01開始算起的
int gettimeofday(struct timeval *,void *);
如果第二個參數不爲NULL,結果不可預料
-
設置定時器
//參數1:定時器類型 //參數2:指定的定時器 //參數3:調用setitimer之前的舊定時器 int setitimer(int,const struct itimerval *,struct itimerval *); // 成功返回0 //是把你返回-1
-
獲取定時器
int getitimer(int,struct itimerval*); //example: getitimer(ITIMER_REAL,&value);
測試代碼
#include<iostream>
#include<sys/time.h>
#include<signal.h>
using namespace std;
void testFun(int a)
{
cout<<"Hello,Linux timer~"<<endl;
}
int main()
{
struct timeval curtime;
gettimeofday(&curtime,NULL);
cout<<"curtime.tv_sec:"<<curtime.tv_sec<<endl;
cout<<"curtime.tv_usec:"<<curtime.tv_usec<<endl;
struct itimerval timer;
//週期定時器間隔
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec =1000*500;//0.5s=500ms=500*1000us
//從設置定時器開始到第一次定時器生效的時間
timer.it_value.tv_sec =1;//1秒
timer.it_value.tv_usec =0;
setitimer(ITIMER_REAL, &timer, NULL);
signal(SIGALRM, testFun);
while(1);
return 0;
}
編譯:
g++ timer_test.cpp -o timer_test
注意:
tv_usec
的值必須小於1000*1000
,當等於1000*1000
微秒時,應設置tv_sec=1
,否則程序將出現未響應的狀態~
sigaction函數
頭文件:#include <signal.h>
功能:檢查或修改與指定信號相關聯的處理動作(可同時兩種動作)
//signum:指定要捕獲的信號類型
//act:指定新的信號處理方式
//oldact:輸出先前信號的處理方式,通常爲NULL
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
數據結構:
//sa_handler:函數指針,和signal()的參數handler相同,代表新的信號處理函數,其他意義請參考signal()
//sa_sigaction:是另一個信號處理函數,有三個參數,可獲得關於信號的更詳細的信息;當 sa_flags 成員的值包含了 SA_SIGINFO 標誌時,系統將使用 sa_sigaction 函數作爲信號處理函數,否則使用 sa_handler 作爲信號處理
//sa_mask:用來指定在信號處理函數執行期間需要被屏蔽的信號,特別是當某個信號被處理時,它自身會被自動放入進程的信號掩碼,因此在信號處理函數執行期間這個信號不會再度發生。
//sa_flags:用來設置信號處理的其他相關操作
// SA_RESETHAND:當調用信號處理函數時,將信號的處理函數重置爲缺省值SIG_DFL
// SA_RESTART:如果信號中斷了進程的某個系統調用,則系統自動啓動該系統調用(使被信號打斷的系統調用自動重新發起)
// SA_NODEFER :一般情況下, 當信號處理函數運行時,內核將阻塞該給定信號。但是如果設置了 SA_NODEFER標記, 那麼在該信號處理函數運行時,內核將不會阻塞該信號(使對信號的屏蔽無效,即在信號處理函數執行期間仍能發出這個信號)
// SA_NOCLDSTOP:使父進程在它的子進程暫停或繼續運行時不會收到 SIGCHLD 信號。
// SA_NOCLDWAIT:使父進程在它的子進程退出時不會收到 SIGCHLD 信號,這時子進程如果退出也不會成爲殭屍進程。
// SA_SIGINFO:使用 sa_sigaction 成員而不是 sa_handler 作爲信號處理函數。
//sa_restorer:此參數未使用,據說已廢棄
struct sigaction
{
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
測試代碼:
具體看這篇博文→https://www.cnblogs.com/Jacket-K/p/8364874.html
其他結論
- 默認情況下,信號將由主進程接收處理,就算信號處理函數是由子線程註冊的
- 對信號的處理是進程中所有的線程共享的
參考文獻:
- https://www.beck-ipc.com/api_files/sc145/libc/Elapsed-Time.html
- https://www.cnblogs.com/jordan-tao/archive/2012/11/03/linux_sys_times.html
- https://www.cnblogs.com/wblyuyang/archive/2012/11/13/2768923.html
- https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_time.h.html
- https://www.cnblogs.com/love-DanDan/p/8724237.html
- https://blog.csdn.net/weibo1230123/article/details/81411827
- https://baike.baidu.com/item/sigaction/4515754?fr=aladdin
- https://blog.csdn.net/weibo1230123/article/details/81411827
- https://www.cnblogs.com/Jacket-K/p/8364874.html
- https://blog.csdn.net/u014530704/article/details/81415153