天天看點

20191324讀書筆記8

第五章 定時器及時鐘服務

硬體定時器

  • 定時器是由時鐘源和可程式設計計數器組成的硬體裝置。時鐘源通常是一個晶體振蕩器,會産生周期性電信号,以精确的頻率驅動計數器。使用一個倒計時值對計數器進行程式設計,每個時鐘信号減1。當計數減為0時,計數器向CPU生成一個定時器中斷,将計數值重新加載到計數器中,并重複倒計時。計數器周期稱為定時器刻度,是系統的基本計時單元。

個人計算機定時器

  • 實時時鐘(RTC) : RTC由一個小型備用電池供電。即使在個人計算機關機時,它 也能連續運作。它用于實時提供時間和日期資訊。當Linux啟動時,它使用RTC更新系統 時間變量.以與目前時間保持一緻。在所有類Unix系統中,時間變量是一個長整數,包含 從1970年1月1日起經過的秒數。
  • 可程式設計間隔定時器(PIT): PIT是與CPU分離的一個硬體定時器。可 對它進行程式設計,以提供以毫秒為機關的定時器刻度。在所有I/O裝置中,PIT可以最高優先 級IRQ0中斷。PIT定時器中斷由Linux核心的定時器中斷處理程式來處理,為系統操作提 供基本的定時單元,例如程序排程、程序間隔定時器和其他許多定時事件。
  • 多核CPU中的本地定時器:在多核CPU中,每個核都 是一個獨立的處理器,它有自己的本地定時器,由CPU時鐘驅動。
  • 高分辨率定時器:大多數電腦都有一個時間戳定時器(TSC),由系統時鐘驅動。它 的内容可通過64位TSC寄存器讀取。由于不同系統主機闆的時鐘頻率可能不同,TSC不适合 作為實時裝置,但它"提供納秒級的定時器分辨率。一些高端個人計算機可能還配備有專用 高速定時器,以提供納秒級定時器分辨率.

CPU操作

  • 每個CPU都有一個程式計數器(PC),也稱為指令指針(IP),以及一個标志或狀态寄 存器(SR)、一個堆棧指針(SP)和幾個通用寄存器,當PC指向記憶體中要執行的下一條指 令時,SR包含CPU的目前狀态,如操作模式、中斷掩碼和條件碼,SP指向目前堆棧棧頂。
  • CPU操作可通過無限循環進行模組化。

中斷處理

  • 在每條指令執行結束時,如果CPU未處于接受中斷的狀态,即在CPU的狀态寄存器中屏蔽了中斷。它将忽略中斷請求.使其處于挂起狀态并繼續執行下一條指令。

時鐘服務函數

  • clock_t times(struct tms *buf);可用于擷取某程序的具體執行時間。它将程序時間存儲在struct tms buf中:
clock_t		// user mode time
clock_t	tms_stime;	// system mode time
clock_t	tms_cutime;	// user time of children
clock_t	tms_cstime;	// system time of children
           
  • date:列印或設定系統日期和時間。
  • time:報告程序在使用者模式和系統模式下的執行時間和總時間。
  • hwclock:查詢并設定硬體時鐘(RTC),也可以通過BIOS來完成。
  • 間隔定時器的值用以下結構體(在<sys/time.h>中)定義:

struct itimerval {

struct timeval it_inteirval; /* interval for periodic timer / struct timeval it_value; / time until next expiration /

};

struct timeval (

time_t tv_sec; / seconds /

suseconds_t tv_usec; / microseconds */

);

臨界區

實踐

示例5.3:time.c

#include <stdio.h>
#include <time.h>
time_t start,end;
int main()
{
int i;
start = time(NULL);
printf ("start=%ld\n", start);
for (i=0; i<123456789; i++); // delay to simulate computation
end = time (NULL);
printf ("end =%ld time=%ld\n" , end, end-start);
}
           

運作截圖

示例5.1 gettimeofday.c

#include <stdio.h>
#include <string.h>
#include <sys/time.h>

int main()
{
    struct timeval tv;

    gettimeofday(&tv, NULL);

    printf("tv_sec: %d\n", tv.tv_sec);
    printf("tv_usec: %d\n", tv.tv_usec);

    return 0;
}