歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

淺談時間函數gettimeofday的成本

我們在程序中會頻繁地取當前時間,例如處理一個http請求時,兩次調用gettimeofday取差值計算出處理該請求消耗了多少秒。這樣的調用無處不在,所以我們有必要詳細了解下,gettimeofday這個函數做了些什麼?內核1ms一次的時鐘中斷處理真的可以支持tv_usec字段達到微秒精度嗎?它的調用成本在i386/x86_64體系架構上代價一樣嗎?如果在系統繁忙時,頻繁的調用它有問題嗎?

gettimeofday是C庫提供的函數(不是系統調用),它封裝了內核裡的sys_gettimeofday系統調用,就是說,歸根到底是系統調用。

但是,內核對於x86_64體系結構下,除了普通的系統調用外,還提供了sysenter和vsyscall方式來獲取內核態的數據。目前我們使用的操作系統大都是x86_64體系的,如果我們用strace命令跟蹤,就會發現gettimeofday命令實際上沒有執行系統調用(i386體系會有),這是因為:x86_64體系上,使用vsyscall實現了gettimeofday這個系統調用。具體就是,創建了一個共享的內存頁面,它是在內核態的,它的數據由內核來維護,但是,用戶態也有權限訪問這個內核頁面,由此,不通過中斷gettimeofday也就拿到了系統時間。

接下來,我來詳細回答以上4個問題。

一、gettimeofday做了些什麼?

它把內核保存的牆上時間和jiffies綜合處理後返回給用戶。解釋下牆上時間和jiffies是什麼:1、牆上時間就是實際時間(1970/1/1號以來的時間),它是由我們主板電池供電的(裝過PC機的同學都了解)RTC單元存儲的,這樣即使機器斷電了時間也不用重設。當操作系統啟動時,會用這個RTC來初始化牆上時間,接著,內核會在一定精度內根據jiffies維護這個牆上時間。2、jiffies就是操作系統啟動後經過的時間,它的單位是節拍數。有些體系架構,1個節拍數是10ms,但我們常用的x86體系下,1個節拍數是1ms。也就是說,jiffies這個全局變量存儲了操作系統啟動以來共經歷了多少毫秒。我們來看看gettimeofday是如何做的。首先它調用了sys_gettimeofday系統調用。

[cpp]
  1. asmlinkage long sys_gettimeofday(struct timeval __user *tv, struct timezone __user *tz)  
  2. {  
  3.     if (likely(tv != NULL)) {  
  4.         struct timeval ktv;  
  5.         do_gettimeofday(&ktv);  
  6.         if (copy_to_user(tv, &ktv, sizeof(ktv)))  
  7.             return -EFAULT;  
  8.     }  
  9.     if (unlikely(tz != NULL)) {  
  10.         if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))  
  11.             return -EFAULT;  
  12.     }  
  13.     return 0;  
  14. }  
大家看到,它調用do_gettimeofday函數取到當前時間存儲到局部變量ktv上,www.linuxidc.com 然後調用copy_to_user把結果復制到用戶空間。每個體系都有自己的實現,我這裡就簡單列下x86_64體系下do_gettimeofday的實現:

[cpp]
  1. void do_gettimeofday(struct timeval *tv)  
  2. {  
  3.     unsigned long seq, t;  
  4.     unsigned int sec, usec;  
  5.   
  6.     do {  
  7.         seq = read_seqbegin(&xtime_lock);  
  8.   
  9.         sec = xtime.tv_sec;  
  10.         usec = xtime.tv_nsec / 1000;  
  11.   
  12.         /* i386 does some correction here to keep the clock  
  13.            monotonous even when ntpd is fixing drift. 
  14.            But they didn't work for me, there is a non monotonic 
  15.            clock anyways with ntp. 
  16.            I dropped all corrections now until a real solution can 
  17.            be found. Note when you fix it here you need to do the same 
  18.            in arch/x86_64/kernel/vsyscall.c and export all needed 
  19.            variables in vmlinux.lds. -AK */   
  20.   
  21.         t = (jiffies - wall_jiffies) * (1000000L / HZ) +  
  22.             do_gettimeoffset();  
  23.         usec += t;  
  24.   
  25.     } while (read_seqretry(&xtime_lock, seq));  
  26.   
  27.     tv->tv_sec = sec + usec / 1000000;  
  28.     tv->tv_usec = usec % 1000000;  
  29. }  
大家看到,只是把xtime加以jiffies修正後返回給用戶而已。而xtime變量和jiffies的維護更新頻率,就決定了時間精度,上面說了,每10或者1ms才處理一次時鐘中斷,難道精度只到1ms嗎?繼續往下。
Copyright © Linux教程網 All Rights Reserved