一塘幅、Linux時間類型
在Linux系統(tǒng)當(dāng)中,時間分為兩種類型:格林威治時間和日歷時間尿贫。
Coordinated Universal Time(UTC)是世界標(biāo)準(zhǔn)的時間电媳,即常說的格林威治標(biāo)準(zhǔn)時間(Greenwich Mean Time,GMT)庆亡;UTC與GMT兩者幾乎是同一概念匾乓,都是指格林威治時間,只不過UTC的稱呼更為正式一點(diǎn)又谋。兩者的區(qū)別是UTC是天文學(xué)上的概念拼缝,而GMT是基于一個原子鐘娱局。
Calendar Time是用“一個標(biāo)準(zhǔn)時間點(diǎn)(如1970年1月1日0點(diǎn))到此時經(jīng)過的秒數(shù)”來表示的時間,即日歷時間咧七;它與格林威治時間不同衰齐。
GMT是中央市區(qū),北京在東8區(qū)继阻,相差8個小時耻涛,所以北京時間=GMT時間+8小時。
++獲取系統(tǒng)時間函數(shù)有:time()瘟檩、gettimeofday()抹缕;++
++設(shè)置系統(tǒng)時間函數(shù)有:stime()、settimeofday()芒帕;++
二歉嗓、Linux時間格式
2.1 time_t 時間類型
time_t類型定義在time.h中:
#ifndef __TIME_T
#define __TIME_T
typedef long time_t
#endif
可見丰介,time_t實(shí)際是一個長整型背蟆。其值表示為從UTC(coordinated universal time)時間1970年1月1日00時00分00秒(也稱為Linux系統(tǒng)的Epoch時間)到當(dāng)前時刻的秒數(shù)。由于time_t類型長度的限制哮幢,它所表示的時間不能晚于2038年1月19日03時14分07秒(UTC)带膀。為了能夠表示更久遠(yuǎn)的時間,可用64位或更長的整型數(shù)來保存日歷時間橙垢。
time_t類型的時間可以通過time()函數(shù)獲取垛叨。
2.2 struct tm時間類型
struct tm結(jié)構(gòu)在time.h中定義為:
#include <time.h>
struct tm {
int tm_sec; /* seconds */
int tm_min; /* minutes */
int tm_hour; /* hours */
int tm_mday; /* day of the month */
int tm_mon; /* month */
int tm_year; /* year */
int tm_wday; /* day of the week */
int tm_yday; /* day in the year */
int tm_isdst; /* daylight saving time */
};
ANSI C標(biāo)準(zhǔn)稱使用tm結(jié)構(gòu)的這種時間為分解時間(broken-down time)。其成員介紹如下:
- tm_sec:秒柜某,取值區(qū)間為[0嗽元,59];
- tm_min:分喂击,取值區(qū)間為[0剂癌,59];
- tm_hour:時翰绊,取值區(qū)間為[0佩谷,23];
- tm_mday:日期监嗜,取值區(qū)間為[1谐檀,31];
- tm_mon:月份裁奇,取值區(qū)間為[0桐猬,11];
- tm_year:年份刽肠,其值為1900年至今的年數(shù)课幕;
- tm_wday:星期厦坛,取值區(qū)間為[0,6]乍惊,0代表星期天杜秸,1代表星期一,以次類推润绎;
- tm_yday:從年的1月1日開始的天數(shù)撬碟,取值區(qū)間為[0,365]莉撇,0代表1月1日呢蛤;
- tm_isdst:夏令時標(biāo)識符,使用夏令時棍郎,tm_isdst為正其障;不使用夏令時,tm_isdst為0涂佃;不了解情況時励翼,tm_isdst為負(fù)。
使用gmtime()和localtime()可將time_t時間類型轉(zhuǎn)換為struct tm結(jié)構(gòu)體辜荠;
使用mktime()可將struct tm結(jié)構(gòu)體轉(zhuǎn)換為time_t時間類型汽抚;
使用asctime()將struct tm轉(zhuǎn)換為字符串形式。
2.3 struct timeval時間類型
struct timeval結(jié)構(gòu)體在sys/time.h中定義如下:
#include <sys/time.h>
struct timeval {
time_t tv_sec; /* seconds:秒 */
suseconds_t tv_usec; /* microseconds:微妙 */
};
tv_sec是time_t時間類型伯病,其值也表示為從UTC(coordinated universal time)時間1970年1月1日00時00分00秒(也稱為Linux系統(tǒng)的Epoch時間)到當(dāng)期時刻的秒數(shù)造烁。
設(shè)置時間函數(shù)settimeofday()與獲取時間函數(shù)gettimeofday()均使用該事件類型作為參數(shù)傳遞。
2.4 struct timespec時間類型
struct timespec結(jié)構(gòu)體在time.h中定義為:
typedef long time_t;
struct timespec {
time_t tv_sec; /* seconds:秒 */
long tv_nsec; /* microseconds:納妙 */
};
它是POSIX.4標(biāo)準(zhǔn)定義的時間結(jié)構(gòu)午笛,精確度到納秒惭蟋,一般由clock_gettime(clockid_t, struct timespec *)獲取特定時鐘的時間。常用如下4種時鐘:
- CLOCK_REALTIME 統(tǒng)當(dāng)前時間药磺,從1970年1.1日算起
- CLOCK_MONOTONIC 系統(tǒng)的啟動時間告组,不能被設(shè)置
- CLOCK_PROCESS_CPUTIME_ID 本進(jìn)程運(yùn)行時間
- CLOCK_THREAD_CPUTIME_ID 本線程運(yùn)行時間
三、Linux時間編程接口
接下來介紹的時間編程函數(shù)接口均屬于Linux系統(tǒng)調(diào)用函數(shù)与涡。
3.1 time()函數(shù)
【函數(shù)原型】:
#include <time.h>
time_t time(time_t *tloc);
【函數(shù)說明】:
該函數(shù)用于獲取日歷時間惹谐,即從1970年1月1日0點(diǎn)到現(xiàn)在所經(jīng)歷的秒數(shù)。參數(shù)tloc通常設(shè)置為NULL驼卖,若tloc非空氨肌,time()函數(shù)也會將返回值存到tloc指針指向的內(nèi)存中。
【返回值】:
該函數(shù)執(zhí)行成功返回秒數(shù)酌畜,失敗則返回((time_t)-1)值怎囚,錯誤原因存于errno中。
【使用例程】:
#include <stdio.h>
#include <time.h>
int main(void)
{
time_t seconds = 0;
seconds = time((time_t *)NULL);
printf("seconds = %d\n",seconds);
return 0;
}
執(zhí)行結(jié)果為:
seconds = 1434620150
通常用戶得到日歷時間的秒數(shù)沒有實(shí)際的意義,但可以為時間轉(zhuǎn)化做一些輔助性質(zhì)的工作恳守。為了更好的利用時間考婴,用戶需要將這些秒數(shù)轉(zhuǎn)換為更易接受的時間表示方式,這些表示時間的方式有格林威治時間催烘、本地時間等沥阱。
3.2 stime()函數(shù)
【函數(shù)原型】:
#define _SVID_SOURCE /* glibc2 needs this */
#include <time.h>
int stime(time_t *t);
【函數(shù)說明】:
該函數(shù)用于設(shè)置系統(tǒng)時間,參數(shù)t指向time_t時間格式變量伊群,表示從UTC(coordinated universal time)時間1970年1月1日00時00分00秒(也稱為Linux系統(tǒng)的Epoch時間)到當(dāng)前時刻的秒數(shù)考杉。
函數(shù)執(zhí)行成功返回0,失敗返回-1舰始,并將錯誤代碼放在errno中崇棠。
3.3 gmtime()函數(shù)
【函數(shù)原型】:
#include <time.h>
struct tm *gmtime(const time_t *timep);
struct tm *gmtime_r(const time_t *timep, struct tm *result);
【函數(shù)說明】:
該函數(shù)將time()函數(shù)獲取的日歷時間轉(zhuǎn)化為tm結(jié)構(gòu)體表示的格林威治標(biāo)準(zhǔn)時間,并保存在struct tm結(jié)構(gòu)體中丸卷。參數(shù)是time()函數(shù)獲取的日歷時間枕稀。
gmtime_r()是gmtime()的線程安全版本,在libc5.2.5及以后版本中可用谜嫉。
3.4 localtime()函數(shù)
【函數(shù)原型】:
#include <time.h>
struct tm *localtime(const time_t *timep);
struct tm *localtime_r(const time_t *timep, struct tm *result);
【函數(shù)說明】:
該函數(shù)將time()函數(shù)獲取的日歷時間轉(zhuǎn)化為tm結(jié)構(gòu)體表示的本地時區(qū)時間萎坷,并保存至struct tm結(jié)構(gòu)體中。參數(shù)是time()函數(shù)獲取的日歷時間骄恶。
localtime_r()是localtime()的線程安全版本食铐,在libc5.2.5及以后版本中可用匕垫。
【使用實(shí)例】:
#include <stdio.h>
#include <time.h>
int main(void)
{
time_t seconds = 0;
struct tm *utc_time = NULL;
struct tm *local_time = NULL;
seconds = time((time_t *)NULL);
printf("seconds = %d\n",seconds);
utc_time = gmtime(&seconds);
printf("UTC hour is : %d\n",utc_time->tm_hour);
local_time = localtime(&seconds);
printf("Local hour is : %d\n",local_time->tm_hour);
return 0;
}
執(zhí)行結(jié)果為:
seconds = 1434621313
UTC hour is : 9 //格林威治時間是9點(diǎn)
Local hour is : 17 //Linux系統(tǒng)的當(dāng)前時間是17點(diǎn)
在命令行中執(zhí)行data命令僧鲁,可以看到:
Thu Jun 18 17:59:30 CST 2015
說明date命令打印的是Linux系統(tǒng)的本地時間。
3.5 ctime()函數(shù)
【函數(shù)原型】:
#include <time.h>
char *ctime(const time_t *timep);
char *ctime_r(const time_t *timep, char *buf);
【函數(shù)說明】:
該函數(shù)將timep指向的日歷時間(time_t時間類型)轉(zhuǎn)化為本地時間的字符串形式象泵,并返回該字符串指針寞秃,參數(shù)是time()函數(shù)返回的日歷時間。
ctime_r()是ctime()的線程安全版本偶惠,在libc5.2.5及以后版本中可用春寿。
【函數(shù)使用步驟】:
使用time()獲取日歷時間—>使用ctime()將日歷時間直接轉(zhuǎn)換為本地時間字符串。
3.6 asctime()函數(shù)
【函數(shù)原型】:
#include <time.h>
time_t asctime(const struct tm *tm);
char *asctime_r(const struct tm *tm, char *buf);
【函數(shù)說明】:
該函數(shù)將struct tm結(jié)構(gòu)體時間轉(zhuǎn)化為字符串形式忽孽,并返回該字符串指針绑改,參數(shù)是gmtime()函數(shù)或localtime()函數(shù)返回的struct tm結(jié)構(gòu)體時間。
asctime_r()是asctime()的線程安全版本兄一,在libc5.2.5及以后版本中可用厘线。
【函數(shù)使用步驟】:
- 方法一:使用time()獲取日歷時間—>使用gmtime()將日歷時間轉(zhuǎn)化為格林威治時間—>使用asctime()將struct tm格式的時間轉(zhuǎn)化為字符串;
- 方法二:使用time()獲取日歷時間—>使用localtime()將日歷時間轉(zhuǎn)化為本地時間—>使用asctime()將struct tm格式的時間轉(zhuǎn)化為字符串出革;
【使用例程】:
#include <stdio.h>
#include <time.h>
int main(void)
{
time_t t;
char *ptr;
struct tm *utc;
struct tm *local;
t = time((time_t *)NULL);
printf("seconds = %d\n",t);
ptr = ctime(&t);
printf("Local time is : %s\n",ptr);
utc = gmtime(&t);
ptr = asctime(utc);
printf("UTC time is :%s\n",ptr);
local = localtime(&t);
ptr = asctime(local);
printf("Local time is :%s\n",ptr);
return 0;
}
執(zhí)行結(jié)果為:
seconds = 1434622915
Local time is : Thu Jun 18 18:21:55 2015
UTC time is :Thu Jun 18 10:21:55 2015
Local time is :Thu Jun 18 18:21:55 2015
在命令行終端中執(zhí)行date命令造壮,結(jié)果如下:
Thu Jun 18 18:24:32 CST 2015
3.7 mktime()函數(shù)
【函數(shù)原型】:
#include <time.h>
time_t mktime(struct tm *p_tm);
【函數(shù)說明】:
該函數(shù)將p_tm指向的tm結(jié)構(gòu)體時間類型轉(zhuǎn)換成從1970年1月1日00時00分00秒至今的GMT時間經(jīng)過的秒數(shù)。
【函數(shù)實(shí)例】:
#include <time.h>
#include <stdio.h>
int main(void)
{
time_t timep;
struct tm *p_tm;
timep = time((time_t *)NULL);
printf("time():%d\n",timep);
p_tm = local(&timep);
timep = mktime(p_tm);
printf("time()->localtime()->mktime():%d\n",timep);
return 0;
}
3.8 difftime()函數(shù)
【函數(shù)原型】:
#include <time.h>
double difftime(time_t timep1, time_t timep2);
【函數(shù)說明】:
difftime()函數(shù)比較參數(shù)timep1和timep2時間是否相同骂束,并返回之間相差的秒數(shù)耳璧,返回類型為double成箫。
【使用實(shí)例】:
#include <time.h>
#include <stdio.h>
int main(void)
{
time_t timep1,timep2;
timep1 = time(NULL);
sleep(2);
timep2 = time(NULL);
printf("The difference is %f seconds\n", difftime(timep1, timep2));
return 0;
}
3.9 gettimeofday()函數(shù)
【函數(shù)原型】:
#include <sys/time.h>
int gettimeofday(struct timeval *tv, struct timezone *tz);
【函數(shù)說明】:
該函數(shù)用于獲取從UTC(coordinated universal time)時間1970年1月1日00時00分00秒(也稱為Linux系統(tǒng)的Epoch時間)到當(dāng)前時刻的時間差,并將此時間存入tv指向的結(jié)構(gòu)體中旨枯,當(dāng)?shù)貢r區(qū)信息則放到tz指向的結(jié)構(gòu)體中蹬昌;該函數(shù)常用于計(jì)算耗時。函數(shù)執(zhí)行成功返回0攀隔,否則返回-1凳厢,錯誤代碼存于errno。
【參數(shù)說明】:
參數(shù)tv用于存放返回從UTC(coordinated universal time)時間1970年1月1日00時00分00秒(也稱為Linux系統(tǒng)的Epoch時間)到當(dāng)前時刻的時差竞慢,時間差以秒或微妙為單位先紫;
參數(shù)tz常設(shè)置為NULL,因?yàn)閘ibc或glibc中并未支持tz筹煮,因此在Linux中未使用遮精;struct timezone結(jié)構(gòu)體定義如下:
#include <sys/time.h>
struct timezone {
int tz_minuteswest; /* miniutes west of Greenwich:和GMT時間差了多少分鐘 */
int tz_dsttime; /* type of DST correction:日光節(jié)約時間的狀態(tài) */
};
tz_dsttime所代表的狀態(tài)如下:
DST_NONE /* not on dst */
DST_USA /* USA style dst */
DST_AUST /* Australian style dst */
DST_WET /* Western European dst */
DST_MET /* Middle European dst */
DST_EET /* Eastern European dst */
DST_CAN /* Canada */
DST_GB /* Great Britain and Eire */
DST_RUM /* Rumania */
DST_TUR /* Turkey */
DST_AUSTALT /* Australian style with shift in 1986 */
【常用用法】:
在做某件事之前調(diào)用gettimeofday(),在做完該事情之后調(diào)用gettimeofday()败潦,兩個函數(shù)的tv參數(shù)返回值的差就是該事件所消耗的時間本冲。
【使用實(shí)例】:
#include <stdio.h>
#include <sys/time.h>
void function(void)
{
unsigned int i,j,k;
for(i = 0;i < 500;i++)
for(j = 0;j < 500;j++)
k++;
}
int main(void)
{
time_t t;
float timeuse;
struct timeval tpstart,tpend;
t = time((time_t *)NULL);
printf("seconds is %d\n",t);
gettimeofday(&tpstart,NULL);
printf("seconds is %d,usec is %d\n",tpstart.tv_sec,tpstart.tv_usec);
function();
gettimeofday(&tpend,NULL);
timeuse = 1000*1000*(tpend.tv_sec - tpstart.tv_sec) + tpend.tv_usec - tpstart.tv_usec;
timeuse /= 1000*1000;
printf("User time:%f\n",timeuse);
return 0;
}
執(zhí)行結(jié)果為:
User time:0.000727
3.10 settimeofday()函數(shù)
【函數(shù)原型】:
#include <sys/time.h>
int settimeofday(const struct timeval *tv , const struct timezone *tz);
【函數(shù)說明】:
該函數(shù)把當(dāng)前時間設(shè)成由tv指向的結(jié)構(gòu)體數(shù)據(jù);當(dāng)tz指針不為空時劫扒,則設(shè)成tz指向的結(jié)構(gòu)體數(shù)據(jù)檬洞。函數(shù)執(zhí)行成功返回0,否則返回-1沟饥,錯誤代碼存于errno添怔。只有root權(quán)限才能使用此函數(shù)修改時間。
3.11 strftime()函數(shù)
【函數(shù)原型】:
#include <time.h>
size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);
【函數(shù)說明】:
該函數(shù)將參數(shù)tm結(jié)構(gòu)的時間結(jié)構(gòu)贤旷,參照參數(shù)format所指定的字符串格式做轉(zhuǎn)換广料,轉(zhuǎn)換后的字符串內(nèi)容將復(fù)制到參數(shù)s所指的字符串?dāng)?shù)組中,該字符串的最大長度為參數(shù)max所控制幼驶。下面是參數(shù)format的格式指令:
- %a:當(dāng)?shù)匦瞧谌掌诘拿Q縮寫艾杏,如Sun;
- %A:當(dāng)?shù)匦瞧谌掌诘拿Q全稱,如Sunday;
- %b:當(dāng)?shù)卦路莸挠⑽目s寫敌土;
- %h:當(dāng)?shù)卦路莸挠⑽目s寫券敌;
- %B:當(dāng)?shù)卦路莸拿Q全稱;
- %m:月份,表示法為01~12;
- %C:以year/100表示年份;
- %d:月里的天數(shù)元旬,表示法為01~31;
- %e:月里的天數(shù),表示法為1~31匀归;
- %c:當(dāng)?shù)剡m當(dāng)?shù)娜掌谂c時間表示法表示完整時間坑资;
- %H:以24小時制表示小時數(shù),表示法為00~23穆端;
- %k:以24小時制表示小時數(shù)袱贮,表示法為0~23;
- %l:以12小時制表示小時數(shù)体啰,表示法為01~12攒巍;
- %M:分鐘數(shù),表示法為00~59荒勇;
- %S:秒數(shù)柒莉,00~59;
- %s:從1970年1月1日0時算起至今的UTC時間所經(jīng)過的秒數(shù)沽翔;
- %j:一年中的天數(shù)(001~366)兢孝;
- %u:一星期中的星期日期,范圍1~7仅偎,星期一從1開始跨蟹;
- %U:一年中的星期數(shù)(00~53),一月第一個星期日開始為01橘沥;
- %w:一星期中的星期日期窗轩,范圍0~6,星期日從0開始座咆;
- %W:一年中的星期數(shù)(00~53)痢艺,一月第一個星期一開始為01;
- %p:顯示對應(yīng)的AM或PM箫措;
- %P:顯示對應(yīng)的am或pm腹备;
- %R:相當(dāng)于使用“%H:%M”格式衬潦;
- %r:相當(dāng)于使用“%I:%M:%S %P”格式斤蔓;
- %D:相當(dāng)于“%m%d%y”格式,如06/19/15镀岛;
- %T:24小時時間表示弦牡,相當(dāng)于“%H:%M:%S”格式;
- %x:當(dāng)?shù)剡m當(dāng)?shù)娜掌诒硎灸暝氯眨?/li>
- %X:當(dāng)?shù)剡m當(dāng)?shù)臅r間表示時分秒漂羊;
- %y:一世紀(jì)中的年份表示驾锰;
- %Y:完整的公元年份表示;
- %Z:使用的時區(qū)名稱走越;
- %n:同\n椭豫;
- %t:同\t;
- %%:%符號;
返回值復(fù)制到參數(shù)s所指的字符串?dāng)?shù)組的總字符數(shù)赏酥,不包括字符串結(jié)束符喳整。如果返回0,表示未復(fù)制字符串到參數(shù)s內(nèi)裸扶,但不表示一定有錯誤發(fā)生框都。環(huán)境變量TZ和TC_TIME會影響此函數(shù)結(jié)果。
【使用實(shí)例】:
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char outstr[200];
time_t t;
struct tm *tmp;
t = time(NULL);
tmp = localtime(&t);
if (tmp == NULL) {
perror("localtime");
exit(EXIT_FAILURE);
}
if (strftime(outstr, sizeof(outstr), argv[1], tmp) == 0) {
fprintf(stderr, "strftime returned 0");
exit(EXIT_FAILURE);
}
printf("Result string is \"%s\"\n", outstr);
exit(EXIT_SUCCESS);
} /* main */
3.12 strptime()函數(shù)
【函數(shù)原型】:
#define _XOPEN_SOURCE /* glibc2 needs this */
#include <time.h>
char *strptime(const char *s, const char *format, struct tm *tm);
【函數(shù)說明】:
該函數(shù)與scanf類似呵晨,同strftime()函數(shù)相反魏保,將一個字符串格式時間解釋稱為struct tm格式時間。
【使用實(shí)例】:
#include <stdio.h>
#include <time.h>
int main() {
struct tm tm;
char buf[255];
strptime("2001-11-12 18:31:01", "%Y-%m-%d %H:%M:%S", &tm);
strftime(buf, sizeof(buf), "%d %b %Y %H:%M", &tm);
puts(buf);
return 0;
}
3.13 clock()函數(shù)
【函數(shù)原型】:
#include <time.h>
clock_t clock(void);
【函數(shù)說明】:
該函數(shù)用來返回進(jìn)程所占用CPU的大約時間摸屠。
3.14 ftime()函數(shù)
【函數(shù)原型】:
#include <sys/timeb.h>
int ftime(struct timeb *tp);
【函數(shù)說明】:
該函數(shù)將日前時間日期由參數(shù)tp所指向的結(jié)構(gòu)體輸出谓罗,該函數(shù)無論成功還是失敗都返回0。struct timep結(jié)構(gòu)體定義如下:
struct timeb{
time_t time; /* 從1970年1月1日0點(diǎn)至今的秒數(shù) */
unsigned short millitm; /* 為千分之一秒 */
short timezone; /* 為目前時區(qū)和Greenwich相差的時間季二,單位為妙 */
short dstflag; /* 為日光節(jié)約時間的修正狀態(tài)妥衣,若非0為啟用日光節(jié)約時間的修正 */
};
ftime()函數(shù)在4.2的BSD中支持。
3.15 tzset()函數(shù)
【函數(shù)原型】:
#include <time.h>
void tzset(void);
extern char *tzname[2];
extern long timezone;
extern int daylight;
【函數(shù)說明】:
該函數(shù)將環(huán)境變量TZ設(shè)給全局變量tzname戒傻,也就是從環(huán)境變量取得目前當(dāng)?shù)氐臅r區(qū)税手,時間轉(zhuǎn)換函數(shù)會自動調(diào)用此函數(shù)。若TZ為設(shè)置需纳,tzname會依照/etc/localtime找出最接近當(dāng)?shù)氐臅r區(qū)芦倒。若TZ為NULL,或是無法判認(rèn)不翩,則使用UTC時區(qū)兵扬。此函數(shù)總是成功,并初始化tzname口蝠。
四器钟、Linux休眠編程接口
有時候?yàn)榱私档虲PU的占用率及程序的運(yùn)行速度,需要讓程序休眠一段時間妙蔗,在Linux應(yīng)用程序中傲霸,可以使用:sleep()和usleep()函數(shù)實(shí)現(xiàn)。對應(yīng)Linux內(nèi)核中眉反,休眠的函數(shù)有:udelay()昙啄、ndelay()、mdelay()寸五。delay函數(shù)是忙等待梳凛,占用CPU時間,而sleep函數(shù)使調(diào)用進(jìn)程休眠梳杏,并不占用CPU時間韧拒。
4.1 sleep()函數(shù)
【函數(shù)原型】:
#include <unistd.h>
unsigned int sleep(unsigned int seconds);
【函數(shù)說明】:
該函數(shù)使調(diào)用sleep()的程序休眠淹接,直到seconds秒之后才被喚醒。該函數(shù)返回0(seconds時間到了)叛溢,或返回seconds還剩余的秒數(shù)蹈集。
4.2 usleep()函數(shù)
【函數(shù)原型】:
/* BSD version */
#include <unistd.h>
void usleep(unsigned long usec);
/* SUSv2 version */
#define _XOPEN_SOURCE 500
#include <unistd.h>
int usleep(useconds_t usec);
【函數(shù)說明】:
該函數(shù)使調(diào)用usleep()的程序休眠,直到usec微妙之后才被喚醒雇初。該函數(shù)睡眠的實(shí)際時間會比usec略有延長拢肆,因?yàn)槿魏蜗到y(tǒng)活動和時間處理調(diào)用的微處理粒度。
該函數(shù)執(zhí)行成功返回0靖诗,失敗返回-1郭怪。該函數(shù)可以被信號喚醒,同時返回EINTR刊橘。
五鄙才、Linux定時鬧鐘編程接口
Linux應(yīng)用程序?yàn)槲覀兊拿恳粋€進(jìn)程提供了一個定時鬧鐘alarm,當(dāng)定時器指定的時間到時促绵,系統(tǒng)會向調(diào)用進(jìn)程發(fā)送SIGALARM信號攒庵,如果忽略或者不捕獲此信號,則其默認(rèn)動作是終止調(diào)用該alarm函數(shù)的進(jìn)程败晴;當(dāng)然也可以通過signal()函數(shù)向系統(tǒng)注冊一個自己的定時鬧鐘處理函數(shù)浓冒。關(guān)于信號處理方面的知識,可參照信號相關(guān)章節(jié)的內(nèi)容尖坤。
5.1 alarm()函數(shù)
【函數(shù)原型】:
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
【函數(shù)說明】:
alarm()函數(shù)向系統(tǒng)設(shè)定一個鬧鐘稳懒,并在鬧鐘時間到時內(nèi)核向該進(jìn)程發(fā)送SIGALRM信號。
【注意事項(xiàng)】:
- 一個進(jìn)程只能有一個alarm鬧鐘慢味;
- 鬧鐘時間到了后场梆,若不再次調(diào)用alarm(),將不會有新的鬧鐘產(chǎn)生纯路;
- 任何以seconds非0的調(diào)用或油,都將重新更新鬧鐘定時時間,并返回上一個鬧鐘剩余時間驰唬;若為第一次設(shè)置鬧鐘顶岸,則返回0;以seconds為0的調(diào)用定嗓,表示取消以前的鬧鐘蜕琴,并將剩余時間返回。
- 在Linux系統(tǒng)中提到宵溅,sleep()有可能是使用alarm()來實(shí)現(xiàn)的,因此上炎,在一個進(jìn)程中同時使用alarm()和sleep()并不明智恃逻。
【使用實(shí)例】:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
int ret;
sleep(3);
ret = alarm(3);
printf("%d\n",ret);
pause();
printf("This will not been print.\n");
return 0;
}
執(zhí)行結(jié)果為:
0 //第一次為該進(jìn)程設(shè)置鬧鐘
Alarm clock
注意最后一個printf并未打印出來雏搂,因?yàn)槌绦驔]有注冊SIGALARM信號處理函數(shù),系統(tǒng)默認(rèn)處理動作是結(jié)束alarm()調(diào)用進(jìn)程寇损。
5.2 setitimer()函數(shù)
Linux系統(tǒng)為每個進(jìn)程提供了三個獨(dú)立的計(jì)時器凸郑,每個計(jì)時器在不同的時域中遞減。當(dāng)任何一個定時器到點(diǎn)了矛市,都會向進(jìn)程發(fā)送一個信號芙沥,并且重啟計(jì)時器。
【函數(shù)原型】:
#include <sys/time.h>
int getitimer(int which, struct itimerval *value);
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue);
【函數(shù)說明】:
getitimer()函數(shù)獲取ITIMER_REAL浊吏、ITIMER_VIRTUAL或ITIMER_PROF三個定時器中的一個的時間信息而昨,并保存到value指向的對象中。
setitimer()函數(shù)設(shè)置ITIMER_REAL找田、ITIMER_VIRTUAL或ITIMER_PROF三個定時器中的一個的定時時間為value指向的對象歌憨,若ovalue非空,則將老的時間信息保存到該對象中墩衙。
setitimer()比alarm()功能更加強(qiáng)大务嫡,支持3種類型的定時器(但setitimer()并不是標(biāo)準(zhǔn)C庫的函數(shù)):
- ITIMER_REAL:以系統(tǒng)真實(shí)的時間來計(jì)算,它會送出SIGALRM信號漆改;
- ITIMER_PROF:以該進(jìn)程在用戶態(tài)下和內(nèi)核態(tài)下所費(fèi)時間來計(jì)算心铃,它送出SIGPROF信號;
- ITIMER_VIRTUAL:以該進(jìn)程在用戶態(tài)下花費(fèi)的時間來計(jì)算挫剑,它送出SIGVTALRM信號于个;
該函數(shù)執(zhí)行成功返回0,失敗返回-1暮顺,并將錯誤號存放在errno中厅篓。
【參數(shù)說明】:
witch用于指定定時器類型,其取值為上面三種之一捶码;value是struct itimerval的一個實(shí)例羽氮;ovalue參數(shù)不做處理。struct itimerval結(jié)構(gòu)體定義如下:
struct itimerval {
struct timeval it_interval; /* next value */
struct timeval it_value; /* current value */
};
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
it_value變量用于設(shè)置計(jì)時器的計(jì)時時間惫恼,為0時表示禁止档押;it_interval變量用于設(shè)置當(dāng)計(jì)時器到時,重置的時間祈纯,從而實(shí)現(xiàn)循環(huán)定時令宿。也就是說,計(jì)時器從it_value開始遞減腕窥,當(dāng)遞減到0時粒没,向進(jìn)程發(fā)送一個信號,并重置定時器為it_interval簇爆,如此循環(huán)癞松,從而可以實(shí)現(xiàn)循環(huán)鬧鐘的功能爽撒。
【使用實(shí)例】:
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <sys/time.h>
void sig_func(int signo)
{
printf("Catch a signal.\n");
static int realCnt = 0;
static int virtualCnt = 0;
switch(signo)
{
case SIGALRM:
printf("The %d times:SIGALRM\n",realCnt++);
break;
case SIGVTALRM:
printf("The %d times:SIGVTALRM\n",virtualCnt++);
break;
default:
break;
}
}
int main(void)
{
struct itimerval tv,tv1,otv;
signal(SIGALRM,sig_func);
signal(SIGVTALRM,sig_func);
//how long to run the first time
tv.it_value.tv_sec = 3;
tv.it_value.tv_usec = 0;
//after the first time,how long to run next time
tv.it_interval.tv_sec = 2;
tv.it_interval.tv_usec = 0;
if(setitimer(ITIMER_REAL,&tv,&otv) != 0)
{
printf("setitimer err %d\n",errno);
return -1;
}
tv1.it_value.tv_sec = 1;
tv1.it_value.tv_usec = 0;
tv1.it_interval.tv_sec = 1;
tv1.it_interval.tv_usec = 0;
if(setitimer(ITIMER_VIRTUAL,&tv1,&otv) != 0)
{
printf("setitimer err %d\n",errno);
return -1;
}
while(1)
{
sleep(30);
printf("otv:%d,%d,%d,%d\n",otv.it_value.tv_sec,otv.it_value.tv_usec,
otv.it_interval.tv_sec,otv.it_interval.tv_usec);
}
return 0;
}