计算机中的时间
@font-face { font-family: 宋體 }
@font-face { font-family: "@宋體" }
p.MsoNormal, li.MsoNormal, div.MsoNormal { mso-style-parent: ""; margin: 0 0 0.0001pt; text-align: justify; text-justify: inter-ideograph; mso-pagination: none; font-size: 10.5pt; mso-bidi-font-size: 12.0pt; font-family: "Times New Roman"; mso-fareast-font-family: 宋體; mso-font-kerning: 1.0pt }
@page { mso-page-border-surround-header: no mso-page-border-surround-footer: no }
@page Section1 { size: 612.0pt 792.0pt margin-top: 72pt margin-right: 90pt margin-bottom: 72pt margin-left: 90pt mso-header-margin: 36.0pt mso-footer-margin: 36.0pt mso-paper-source: 0 }
div.Section1 { page: Section1 }
寫在前面:時鐘可以說是計算機的心臟,它是分時系統的基礎。如果時鐘反應到應用程序的層面,就是時間,很多應用程序都會涉及到時間處理。本文就來討論一下計算機中的時鐘與時間。
1、操作系統中的時間
在Unix/Linux系統中,有兩個不同的時間:日歷時間和進程時間。
(1)日歷時間:
有些書上又叫系統時間。該值是自1970年1月1日00:00:00以來國際標準時間(U T C)所經過的秒數累計值(早期的手冊稱U T C為格林尼治標準時間)。在PC/AT微機系統中,支撐該時間的硬件是實時鐘RT(Real Time)電路。操作系統在系統初始化的過程中,會從該電路中讀取該時間,并保存在內核變量中。
來看看Linux1.0中相關的代碼
//kernel/time.c
externlongkernel_mktime(structmktime*time);
//初始化時間
voidtime_init(void)
{
structmktimetime;
inti;
/*checkingforUpdate-In-Progresscouldbedonemoreelegantly
*(usingthe"updatefinished"-interruptforexample),butthat
*wouldrequireexcessivetesting.promiseI'lldothatwhenIfind
*thetime.-Torsten
*/
/*readRTCexactlyonfallingedgeofupdateflag*/
for(i=0;i<1000000;i++)/*maytakeupto1second*/
if(CMOS_READ(RTC_FREQ_SELECT)&RTC_UIP)
break;
for(i=0;i<1000000;i++)/*musttryatleast2.228ms*/
if(!(CMOS_READ(RTC_FREQ_SELECT)&RTC_UIP))
break;
do{/*Isn'tthisoverkill?UIPaboveshouldguaranteeconsistency*/
time.sec=CMOS_READ(RTC_SECONDS);
time.min=CMOS_READ(RTC_MINUTES);
time.hour=CMOS_READ(RTC_HOURS);
time.day=CMOS_READ(RTC_DAY_OF_MONTH);
time.mon=CMOS_READ(RTC_MONTH);
time.year=CMOS_READ(RTC_YEAR);
}while(time.sec!=CMOS_READ(RTC_SECONDS));
if(!(CMOS_READ(RTC_CONTROL)&RTC_DM_BINARY)||RTC_ALWAYS_BCD)
{
BCD_TO_BIN(time.sec);
BCD_TO_BIN(time.min);
BCD_TO_BIN(time.hour);
BCD_TO_BIN(time.day);
BCD_TO_BIN(time.mon);
BCD_TO_BIN(time.year);
}
time.mon--;
xtime.tv_sec=kernel_mktime(&time);
}
//kernel/sched.c
//保存系統時間的內核變量
volatilestructtimevalxtime;/*Thecurrenttime*/
//linux/mktime.h
structmktime{
intsec;//秒
intmin;//分鐘
inthour;//小時
intday;//天
intmon;//月
intyear;//年
};
//kernel/mktime.c
//計算1970年1月1日00:00:00以來秒的累計值
longkernel_mktime(structmktime*time)
{
longres;
intyear;
year=time->year-70;
/*magicoffsets(y+1)neededtogetleapyearsright.*/
res=YEAR*year+DAY*((year+1)/4);
res+=month[time->mon];
/*and(y+2)here.Ifitwasn'taleap-year,wehavetoadjust*/
if(time->mon>1&&((year+2)%4))
res-=DAY;
res+=DAY*(time->day-1);
res+=HOUR*time->hour;
res+=MINUTE*time->min;
res+=time->sec;
returnres;
}
//linux/time.h
structtimeval{
longtv_sec;/*seconds*/
longtv_usec;/*microseconds*/
};
(2)進程時間
該時間用來度量進程使用CPU的時間。
來看看Linux 1.0中相應的代碼:
//linux/sched.h
//內核任務的結構定義
structtask_struct{
//…
//依次為:用戶CPU時間,系統CPU時間,子進程用戶CPU時間,子進程系統CPU時間,
//進程開始運行時間
longutime,stime,cutime,cstime,start_time;
//…
}
當度量一個進程的執行時間時,Unix系統使用三個進程時間值:
? 時鐘時間。
? 用戶C P U時間。
? 系統C P U時間。
要取得任一進程的時鐘時間、用戶時間和系統時間很容易——只要執行命令 t i m e ( 1 ),其參數是要度量其執行時間的命令,例如:
$ cd /usr/include
$ time grep _POSIX_SOURCE */*.h > /dev/null
real 0m19.81s
user 0m0.43s
sys 0m4.53s
t i m e命令的輸出格式與所使用的s h e l l有關。
該時間的支撐硬件在PC機中是可編程定時芯片Intel8253(8254)。8254芯片的時鐘輸入頻率是1193180,我們通過設定一定的初始計數值(LATCH),默認值為65535,就能控制該芯片的輸出頻率,默認為1193180/65535hz,例如,假定LATCH=1193180/100,我們就能保證輸出頻率為100hz,即周期為10ms,我們稱為系統的時鐘周期,或者1個系統滴答。這樣,1個系統的滴答就為10ms,這也Linux的默認值。
8254芯片每經過一個滴答時間,就會向CPU發出一個時鐘中斷。Linux會在時鐘中斷處理過程增加內核變量jiffies值,該值累計系統開機以來的經過的時鐘滴答數。
Linux 1.0中的代碼:
//kernel/sched.c
unsignedlongvolatilejiffies=0;//累計系統開機以來的滴答數
2、標準C庫中的時間函數
typedeflongint__clock_t;/*TypeofCPUusagecounts.*/
typedeflongint__time_t;
//time.h
typedef__clock_tclock_t;
#defineCLOCKS_PER_SEC…
typedef__time_ttime_t;
externclock_tclock__P((void));
externtime_ttime__P((time_t*__timer));
clock函數返回當前進程的使用處理器的時間的近似值,每秒的的時鐘滴答數用宏CLOCKS_PER_SEC定義。
在傳統的C語言中,clock函數返回的類型為long(如上),但返回值實際上為unsigned long類型,long是在C語言加入unsigned long之前使用的。計算處理器時間總是使用無符號數算術。一些非標準實現中使用times函數,而不是clock函數,其返回的結構化值報告處理器時間的各個成員,通常以1/60秒為單位。如下:
//sys/times.h
structtms
{
clock_ttms_utime;/*UserCPUtime.*/
clock_ttms_stime;/*SystemCPUtime.*/
clock_ttms_cutime;/*UserCPUtimeofdeadchildren.*/
clock_ttms_cstime;/*SystemCPUtimeofdeadchildren.*/
};
/*StoretheCPUtimeusedbythisprocessandallits
deadchildren(andtheirdeadchildren)inBUFFER.
Returntheelapsedrealtime,or(clock_t)-1forerrors.
AlltimesareinCLK_TCKthsofasecond.*/
externclock_ttimes__P((structtms*__buffer));
標準C中函數time返回當前的日歷時間,返回值類型為time_t。
/time.h
externchar*asctime__P((__conststructtm*__tp));
/*Equivalentto`asctime(localtime(timer))'.*/
externchar*ctime__P((__consttime_t*__timer));
這兩個函數都返回時間的字符串的形式。
//time.h
/*Returnthe`structtm'representationof*TIMER
inUniversalCoordinatedTime(akaGreenwichMeanTime).*/
externstructtm*gmtime__P((__consttime_t*__timer));
/*Returnthe`structtm'representation
of*TIMERinthelocaltimezone.*/
externstructtm*localtime__P((__consttime_t*__timer));
/*Usedbyothertimefunctions.*/
structtm
{
inttm_sec;/*Seconds.[0-60](1leapsecond)*/
inttm_min;/*Minutes.[0-59]*/
inttm_hour;/*Hours.[0-23]*/
inttm_mday;/*Day.[1-31]*/
inttm_mon;/*Month.[0-11]*/
inttm_year;/*Year-1900.*/
inttm_wday;/*Dayofweek.[0-6]*/
inttm_yday;/*Daysinyear.[0-365]*/
inttm_isdst;/*DST.[-1/0/1]*/
#ifdef__USE_BSD
longinttm_gmtoff;/*SecondseastofUTC.*/
__constchar*tm_zone;/*Timezoneabbreviation.*/
#else
longint__tm_gmtoff;/*SecondseastofUTC.*/
__constchar*__tm_zone;/*Timezoneabbreviation.*/
#endif
};
gmtime與localtime將日歷時間轉換成stuct tm類型的分解形式,只不過前者轉換成GMT時間,而后者轉換成本地時間。
總結
- 上一篇: 抽签小程序(C语言随机数)
- 下一篇: Excel—身份证生日提取