内核时钟
內核時鐘
內核時鐘是所有時間相關服務的基礎
概念
內核支持兩種不同的時鐘,分別如下:
①32位的硬件時鐘:是以周期為單位來度量時間的一個高精度的計數器。一個周期的長度取決于內核所使用的板卡硬件,其典型的度量值為納秒
②64位的系統時鐘:?是一個通過嘀嗒來測量內核自初始化以來經歷了多少時間的計數器,嘀嗒的時長是可配置的,其典型值為1~100毫秒
? ? 內核同時提供了各種將時鐘使用的時間單位轉換為標準的時間單位的變量(如秒,毫秒,納秒等等),也可用于兩種不同時間單位之間的轉換
系統時鐘被內核中大部分時間相關的服務所使用,包括內核定時器對象和其它內核對象類型支持的超時服務。為了方便使用,內核的API允許使用毫秒來定義時間長度,并自動將毫秒時間轉換為對應的嘀嗒數
硬時鐘可以用于更高精度的計時,可以完成比系統時鐘精度更高的時間相關服務
時鐘的局限性
系統時鐘的嘀嗒計數是從硬時鐘的周期數衍生出來的。由內核決定多少個時鐘周期和期望的嘀嗒頻率相對應,然后配置硬件在指定的周期后產生一個中斷;每個中斷對應一個嘀嗒周期
note:配置一個較短的嘀嗒時間長度可以保證一個較小時間顆粒度,但同時增加也了大量的工作,讓內核處理更高頻率的嘀嗒中斷。設置嘀嗒時間長度為0,則會關閉?兩個內核時鐘及其相關的服務
任何通過內核API指定的毫秒時間間隔代表的是可發生的最小延時,所以實際經歷的時間可能比設置的要更長
例如:當嘗試獲取一個信號量并指定一個100ms超時延時時,那么在這100ms結束之前內核將不會終止該操作并報告錯誤。然而,該操作可能需要超過100ms的時間才能完成,并且可能在多出的時間里操作成功或者在超時結尾失敗
在一個內核對象操作中,多出的額外時間的長度由如下因素決定:
①在將毫秒轉換為嘀嗒數時的舍入,將引入額外的時間。例如:如果使用了一個時長為10ms的嘀嗒,則25ms的延時將舍入為30ms
②因為在延時計時之前需要等待下一次的嘀嗒中斷,所以這種情況將引入額外的事件。例如:如果采用了一個時長為10ms的嘀嗒,則設定20ms的延時需要內核等待3個嘀嗒發生(而不是2個),因為第一個嘀嗒可能在任何時刻,而計時點到嘀嗒中斷很可能小于10ms;所以只有在第一個嘀嗒發生之后,內核可以通過后續的兩個嘀嗒來確定延時了20ms
實現
使用標準精度來測量時間
該段代碼采用系統時鐘來確定兩個時間點之間經歷了多少時間
使用高精度來測量時間
該段代碼采用硬時鐘來確定兩個時間點之間經歷了多少時間
推薦用法
①請使用基于系統時鐘的服務來執行不需要高精度的時間相關處理,如軟件定時器對象或者線程睡眠
②請使用基于硬時鐘的服務來執行需要精度高于系統時鐘的時間相關處理,如忙等待,或時間顆粒度更小的時間相關的處理
note:當硬時鐘頻率很高時,32位計數器很容易溢出并從零開始循環。所以采用高精度的時間測量時,需要考慮這種超過一個計數周期的情況
配置
相關的配置選項:
- CONFIG_SYS_CLOCK_TICKS_PER_SEC
APIs
下面的內核時鐘APIs都定義在kernel.h中:
- k_uptime_get()
- k_uptime_get_32()
- k_uptime_delta()
- k_uptime_delta_32()
- k_cycle_get_32()
- SYS_CLOCK_HW_CYCLES_TO_NS
- K_NO_WAIT
- K_MSEC
- K_SECONDS
- K_MINUTES
- K_HOURS
- K_FOREVER?
總結