LDD時間,延時及延緩操作-時間及獲取當前時間

1,如何度量時間差,如何比較時間;

      a,時間表示:

            一>  HZ,系統硬件定時器以一定的間隔週期性的產生時鐘中斷,這個間隔週期用HZ的值來表示,這個值是和體系結構相關的,x86體系結構中默認設置爲1000,HZ被定義在linux/param.h頭文件中,可以根據需要修改HZ的值,並重新編譯內核;

                      HZ值得獲取,通過獲取/proc/interrupts 及 /proc/uptime 中從內核空間中導出的值來計算HZ,兩者相除即爲HZ;


              二> 內核計數器,1》用途:內核計數器記錄系統引導以來的硬件定時器產生的時鐘中斷的次數即時鐘滴答數,在每次系統引導的時候初始化爲0;

                                      2》存儲:內核計數器的值用u64(無符號64位)類型的變量 jiffies_64存儲,無論在32位還是64位架構上均是64位,需要注意的是內核計數器的內存溢出問題;

                                      3》編程使用:在內核開發中可以簡單的讀取unsigned long jiffies變量的值;

                                       4》內核計數器讀取:在64位架構上jiffies與jiffies_64位同一個值,而在32位架構上高位和低位讀取不是原子的,讀取高位低位可能變化,讀取低位高位可能變化,所以可能讀取錯誤的值,爲了避免錯誤讀取,內核提供的輔助函數:unsigned long get_jiffies_64(void);來讀取內核計數器的值;


              三>  HZ與內核計數器jiffies_64之間的聯繫:內核計數器/HZ=當前時間(jiffies/HZ=當前時間);


              四> 爲了得到更加精確的時間分辨率,使用與體系結構相關的cpu計數寄存器,例如Inter x86架構cpu的 計數寄存器tsc寄存器;

                      內核提供了原子的讀取tsc寄存器值的宏:unsigned long rdtsc(h32,l32)    unsigned long rdtscl(l32)          long long rdtsdll(var64)

              五> 用戶空間時間表示:毫秒級別 struct timeval{ /*???*/};     納秒級別  struct timespec{/*?????*/};

                     爲了實現用戶空間時間表示與內核空間時間表示的轉換,內核提供了輔助函數(用戶空間結構體與內核空間內核計數器的轉換): 


        b,時間差及時間比較:

               一> 時間比較;

                      通過內核提供的內核宏來比較時間:

                        time_after(a,b); ——a 在 b之後則返回true;

                        time_before(a,b);——a 在 b之前則返回true;

                        time_after_eq(a,b);——a 在 b之後或a與b相等則返回true;

                        time_before_eq(a,b);——a 在 b之前或a與b相等則返回true;

                        上述宏函數的實現原理是:首先檢查內核計數器是否溢出,typecheck(unsigned long,a); 其次,將內核計數器值轉換爲signed long類型,然後做差比較大小;

                二> 時間差:

                         時間差的計算可以用上述時間比較的實現原理,將內核計數器值轉換爲signed long類型的數據然後進行減法運算;


2,獲取當前時間;

            一> 獲取系統引導以來的時鐘滴答數jiffies的值:jiffies/HZ = 當前時間(單位s)-- 計算時間間隔

            二> 牆鍾,內核函數: 

                                   將年月日轉換爲時鐘中斷次數;

                                   unsigned long mktime(unsigned long year,unsigned long month,unsigned long day,unsigned long hour,unsigned long minis , unsigned long seconds);

                                    獲取當前牆鍾時間:

                                   void do_gettimeofday(struct timeval *);

                                      獲取當前內核時間:

                                     struct timespec current_kernel_time();(分辨率是納秒級,當時實際上達不到)  

                                    


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章