1. 程式人生 > >作業系統,核心定時器:使用“訊號”建立一種使用者空間機制來測量一個多執行緒程式的執行時間。

作業系統,核心定時器:使用“訊號”建立一種使用者空間機制來測量一個多執行緒程式的執行時間。

      核心是一個作業系統的核心。它負責管理系統的程序、記憶體、裝置驅動程式、檔案和網路系統,決定著系統的效能和穩定性。 定時器是Linux提供的一種定時服務的機制,它在某個特定的時間喚醒某個程序來進行工作。核心在時鐘中斷髮生後檢測各定時器是否到期,在linux核心中提供了一組函式和資料結構來完成定時觸發工作/週期的事務。

      程序和執行緒都是由作業系統所體會的程式執行的基本單元,系統利用該基本單元實現系統對應用的併發性。一個程序可以有一個或多個執行緒,各個執行緒之間共享程式的記憶體空間(也就是所在程序的記憶體空間)。linux是一個具有保護模式的作業系統。它一直工作在i386 cpu的保護模式之下。記憶體被分為兩個單元: 核心區域和使用者區域。一般地,在使用虛擬記憶體技術的多工系統上,核心和應用有不同的地址空間,因此,在核心和應用之間以及在應用與應用之間進行資料交換需要專門的機制來實現。

      核心定時器是管理核心時間的基礎,用來計算流逝的時間,它以某種頻率(節拍率)自行觸發時鐘中斷。核心定時器在時鐘中斷髮生後,作為軟中斷在下半部的上下文鍾執行的。所有的定時器結構都以連結串列的形式儲存。時鐘中斷髮生後,核心按連結串列順序依次執行。

       一般來說,定時器在超時後會立即執行,但是也有可能被推遲到下一個時鐘節拍才能執行,所以不能用定時器來實現硬實時的操作。又因為核心定時器發生在軟中斷中,因此,定時器執行函式不能夠睡眠,也不能夠持有訊號量。如果對硬體的訪問需要使用訊號量同步,或者可能睡眠(比如需要呼叫kmalloc記憶體分配,但是由於某種原因不能使用GFP_ATOMIC標誌),就不能直接通過定時器來實現了。一個變通的做法是在核心定時器執行函式裡呼叫工作佇列,在工作佇列處理函式中實現對硬體的訪問。

Linux原始碼:

#include <sys/time.h>

#include <pthread.h>

#include <stdio.h>

 

//宣告獲得時間函式

int gettimeofday(struct timeval *tv,struct timezone *tz);

 

//宣告建立定時器函式

//int pthread_create(&id,NULL,(void *) thread,NULL);

 

//宣告執行緒歸併函式

//pthread_join(id,NULL);

 

//定義核心定時器

/***********

struct timeval{

long tv_sec;   //秒數

long tv_usec;  //微秒

};

***********/

 

//子執行緒

void thread(void){

int i;

for(i=0;i<3;i++)

printf("This is a pthread.\n");

}

 

int pthread(void){

pthread_t id;       // 聲明瞭一個pthread_t型的變數

int i,ret;

ret=pthread_create(&id,NULL,(void *) thread,NULL);

if(ret!=0){

printf("Create pthread error!\n");

exit(1);

}

for(i=0;i<3;i++)

printf("This is the main process.\n");

pthread_join(id,NULL);

return(0);

}

 

main(){

struct timeval tpstart,tpend;

/*申請struct timeval的變數,tv_sec返回的是秒數,tv_usec返回的是微秒數*/

float timeuse;

gettimeofday(&tpstart,NULL);

pthread();

gettimeofday(&tpend,NULL);

timeuse=1000000*(tpend.tv_sec-tpstart.tv_sec)+ tpend.tv_usec-tpstart.tv_usec;

timeuse/=1000000;

printf("Used Time:%f sec\n",timeuse);

exit(0);

}

除錯過程:

  1. 開啟Ubuntu虛擬機器;
  2. 開啟終端terminal;
  3. 輸入Linux命令測試:vim timer.c,進入編輯器,編輯源程式;
  4. 編輯源程式結束後,輸入ESC鍵+:wq儲存並退出編輯器。
  5. 編譯源程式,輸入:gcc timer.c -lpthread -o timer.out。(使用pthread API函式,需在程式中增加標頭檔案pthread.h,在編譯時要加上-lpthread選項,pthread執行緒函式位於libpthread.so共享庫中)。

     6.輸入命令./timer.out執行源程式,得到結果輸出。