這篇文章主要講解了“l(fā)inux定時(shí)器的使用方法”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“l(fā)inux定時(shí)器的使用方法”吧!
我們提供的服務(wù)有:成都做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、平原ssl等。為成百上千家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的平原網(wǎng)站制作公司
首先來看看linux操作系統(tǒng)為每一個(gè)進(jìn)程提供的3個(gè)內(nèi)部計(jì)時(shí)器。
ITIMER_REAL: 給一個(gè)指定的時(shí)間間隔,按照實(shí)際的時(shí)間來減少這個(gè)計(jì)數(shù),當(dāng)時(shí)間間隔為0的時(shí)候發(fā)出SIGALRM信號
ITIMER_VIRTUAL: 給定一個(gè)時(shí)間間隔,當(dāng)進(jìn)程執(zhí)行的時(shí)候才減少計(jì)數(shù),時(shí)間間隔為0的時(shí)候發(fā)出SIGVTALRM信號
ITIMER_PROF: 給定一個(gè)時(shí)間間隔,當(dāng)進(jìn)程執(zhí)行或者是系統(tǒng)為進(jìn)程調(diào)度的時(shí)候,減少計(jì)數(shù),時(shí)間到了,發(fā)出SIGPROF信號,這個(gè)和ITIMER_VIRTUAL聯(lián)合,常用來計(jì)算系統(tǒng)內(nèi)核時(shí)間和用戶時(shí)間。
用到的函數(shù)有:
#include
int getitimer(int which, struct itimerval *value);
int setitimer(int which, struct itimerval*newvalue, struct itimerval* oldvalue);
strcut timeval
{
long tv_sec; /*秒*/
long tv_usec; /*微秒*/
};
struct itimerval
{
struct timeval it_interval; /*時(shí)間間隔*/
struct timeval it_value; /*當(dāng)前時(shí)間計(jì)數(shù)*/
};
it_interval用來指定每隔多長時(shí)間執(zhí)行任務(wù), it_value用來保存當(dāng)前時(shí)間離執(zhí)行任務(wù)還有多長時(shí)間。比如說, 你指定it_interval為2秒(微秒為0),開始的時(shí)候我們把it_value的時(shí)間也設(shè)定為2秒(微秒為0),當(dāng)過了一秒, it_value就減少一個(gè)為1, 再過1秒,則it_value又減少1,變?yōu)?,這個(gè)時(shí)候發(fā)出信號(告訴用戶時(shí)間到了,可以執(zhí)行任務(wù)了),并且系統(tǒng)自動(dòng)把it_value的時(shí)間重置為it_interval的值,即2秒,再重新計(jì)數(shù)。
為了幫助你理解這個(gè)問題,我們來看一個(gè)例子:
#include
#include
#include
#include
#include
static char msg[] = "time is running out\n";
static int len;
// 向標(biāo)準(zhǔn)錯(cuò)誤輸出信息,告訴用戶時(shí)間到了
void prompt_info(int signo)
{
write(STDERR_FILENO, msg, len);
}
// 建立信號處理機(jī)制
void init_sigaction(void)
{
struct sigaction tact;
/*信號到了要執(zhí)行的任務(wù)處理函數(shù)為prompt_info*/
tact.sa_handler = prompt_info;
tact.sa_flags = 0;
/*初始化信號集*/
sigemptyset(&tact.sa_mask);
/*建立信號處理機(jī)制*/
sigaction(SIGALRM, &tact, NULL);
}
void init_time()
{
struct itimerval value;
/*設(shè)定執(zhí)行任務(wù)的時(shí)間間隔為2秒0微秒*/
value.it_value.tv_sec = 2;
value.it_value.tv_usec = 0;
/*設(shè)定初始時(shí)間計(jì)數(shù)也為2秒0微秒*/
value.it_interval = value.it_value;
/*設(shè)置計(jì)時(shí)器ITIMER_REAL*/
setitimer(ITIMER_REAL, &value, NULL);
}
int main()
{
len = strlen(msg);
init_sigaction();
init_time();
while ( 1 );
exit(0);
}
該程序的ITMER_REAL定時(shí)器,每隔2秒鐘都會(huì)發(fā)送一個(gè)SIGALRM信號,當(dāng)主函數(shù)接收到了這個(gè)信號之后,調(diào)用信號處理函數(shù)prompt_info在標(biāo)準(zhǔn)錯(cuò)誤上輸出time is running out這個(gè)字符串。
對于ITIMER_VIRTUAL和ITIMER_PROF的使用方法類似,當(dāng)你在setitimer里面設(shè)置的定時(shí)器為ITIMER_VIRTUAL的時(shí)候,你把sigaction里面的SIGALRM改為SIGVTALarm, 同理,ITIMER_PROF對應(yīng)SIGPROF。
不過,你可能會(huì)注意到,當(dāng)你用ITIMER_VIRTUAL和ITIMER_PROF的時(shí)候,你拿一個(gè)秒表,你會(huì)發(fā)現(xiàn)程序輸出字符串的時(shí)間間隔會(huì)不止2秒,甚至5-6秒才會(huì)輸出一個(gè),至于為什么,自己好好琢磨一下^_^
下面我們來看看用sleep以及usleep怎么實(shí)現(xiàn)定時(shí)執(zhí)行任務(wù)。
#include
#include
#include
#include
static char msg[] = "I received a msg.\n";
int len;
void show_msg(int signo)
{
write(STDERR_FILENO, msg, len);
}
int main()
{
struct sigaction act;
union sigval tsval;
act.sa_handler = show_msg;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction(50, &act, NULL);
len = strlen(msg);
while ( 1 )
{
sleep(2); /*睡眠2秒*/
/*向主進(jìn)程發(fā)送信號,實(shí)際上是自己給自己發(fā)信號*/
sigqueue(getpid(), 50, tsval);
}
return 0;
}
看到了吧,這個(gè)要比上面的簡單多了,而且你用秒表測一下,時(shí)間很準(zhǔn),指定2秒到了就給你輸出一個(gè)字符串。所以,如果你只做一般的定時(shí),到了時(shí)間去執(zhí)行一個(gè)任務(wù),這種方法是最簡單的。
下面我們來看看,通過自己計(jì)算時(shí)間差的方法來定時(shí):
#include
#include
#include
#include
#include
static char msg[] = "I received a msg.\n";
int len;
static time_t lasttime;
void show_msg(int signo)
{
write(STDERR_FILENO, msg, len);
}
int main()
{
struct sigaction act;
union sigval tsval;
act.sa_handler = show_msg;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction(50, &act, NULL);
len = strlen(msg);
time(&lasttime);
while ( 1 )
{
time_t nowtime;
/*獲取當(dāng)前時(shí)間*/
time(&nowtime);
/*和上一次的時(shí)間做比較,如果大于等于2秒,則立刻發(fā)送信號*/
if (nowtime - lasttime >= 2)
{
/*向主進(jìn)程發(fā)送信號,實(shí)際上是自己給自己發(fā)信號*/
sigqueue(getpid(), 50, tsval);
lasttime = nowtime;
}
}
return 0;
}
這個(gè)和上面不同之處在于,是自己手工計(jì)算時(shí)間差的,如果你想更精確的計(jì)算時(shí)間差,你可以把 time 函數(shù)換成gettimeofday,這個(gè)可以精確到微妙。
上面介紹的幾種定時(shí)方法各有千秋,在計(jì)時(shí)效率上、方法上和時(shí)間的精確度上也各有不同,采用哪種方法,就看你程序的需要了。
感謝各位的閱讀,以上就是“l(fā)inux定時(shí)器的使用方法”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對linux定時(shí)器的使用方法這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!