1. 程式人生 > >linux核心分析筆記----定時器和時間管理

linux核心分析筆記----定時器和時間管理

在這一次裡,主要講講和時間相關的東西,這個我們都比較熟悉,我就直接如主題。

      首先要明白兩個概念:系統定時器和動態定時器。週期性產生的事件都是有系統定時器驅動的,這裡的系統定時器是一種可程式設計硬體晶片,它能以固定頻率產生中斷。該中斷就是定時器中斷,它所對應的中斷處理程式負責更新系統時間,也負責執行需要週期行執行的任務。系統定時器和時鐘中斷處理程式是Linux系統核心管理機制中的中樞。動態定時器是用來推遲執行程式的工具。核心可以動態建立或銷燬動態定時器。

       核心必須在硬體的幫助下才能計算和管理時間。硬體為核心提供了一個系統定時器用以計算流逝的時間,該時鐘在核心中可看成是一個電子時間資源。系統定時器以某種頻率自行觸發時鐘中斷,該頻率可以通過程式設計預定稱為節拍率(tick rate).當時鍾中斷髮生時,核心就通過一種特殊的中斷處理程式對其進行處理。系統定時器頻率(節拍率)是通過靜態預處理定義的,也就是HZ.在系統啟動時按照HZ值對硬體進行設定。體系結構不一樣,HZ的值也不同,定義在asm/param.h中。剛提到的節拍率就是這個意思。週期是1/HZ秒。最後要說明的是這個HZ值在編寫核心程式碼時,不是固定不變的,而是可調的。當然,對於作業系統而言,也並不是一定要這個固定的時鐘中斷。實際上,核心可以使用動態程式設計定時器操作掛起事件。這裡就不多說了。

       在linux核心裡,有一個叫jiffies的變數(定義在linux/jiffies)記錄了自系統啟動以來產生的節拍的總數。啟動時,核心將該變數初始化為0,此後每次時鐘中斷處理程式都會增加該變數的值。因為一秒內時鐘中斷的次數等於HZ,所以jiffies一秒內增加的值也就為HZ.系統執行時間以秒為單位計算,就等於jiffes/HZ.它作為在計算機表示的變數,就總存在大小,當這個變數增加到超出它的表示上限時,就要回繞到0.這個迴繞看起來很簡單,但實際上還是給我們程式設計造成了很大的麻煩,比如邊界條件判斷時。幸好,核心提供了四個巨集來幫助比較節拍計數,這些巨集定義在linux/jiffies.h可以很好的處理節拍迴繞的情況:

      1    說明:unknown引數通常是jiffies,known引數是需要對比的值。

       如果改變核心中的HZ的值則會給使用者空間中某些程式造成異常結果,這是因為核心是以節拍數/秒的形式給使用者空間匯出這個值的,在這個介面穩定了很長一段時間後,應用程式便逐漸依賴於這個特定的HZ的值了。所以如果在核心中更改了HZ的定義值,就打破了使用者空間的常量關係----使用者空間並不知道這個新的HZ的值。為了解決這個問題,核心必須更改所有匯出的jiffies的值。核心定義了USER_HZ來代表使用者空間看到的HZ值。核心可以使用巨集jiffies_to_clock_t()將一個由HZ表示的節拍計數轉換成一個由USER_HZ表示的節拍數。改巨集的用法取決於USER_HZ是否為HZ的整數倍或相反。當是整數倍時,巨集的形式相當簡單:

?
1 #define jiffies_to_clock_t(x) ((x)/(HZ/USER_HZ));

       如果不是整數倍關係,那麼該巨集就得用更為複雜的演算法了。同樣的,如果是64位系統,核心使用函式jiffies_64_to_clock()將64位的jiffies值的單位從HZ轉換為USER_HZ.

       體系結構提供了兩種裝置進行計時:系統定時器和實時時鐘。系統定時器提供一種週期性觸發中斷機制。實時時鐘(RTC)是用來持久儲存系統時間的裝置,即便系統關閉後,它也可以靠主機板上的微型電池提供的電力保護系統的計時。當系統啟動時,核心通過讀取RTC來初始化牆上時間,該時間存放在xtime變數中,實時時鐘最主要的作用是在啟動時初始化xtime變數。

       有了上面的概念基礎,下面就分析時鐘中斷處理程式。它分為兩個部分:體系結構相關部分和體系結構無關部分。相關的部分作為系統定時器的中斷處理程式而註冊到核心中,以便在產生時鐘中斷時,它能夠相應地執行。執行的工作如下:

1.獲得xtime_lock鎖,以便對訪問jiffies_64和牆上時間xtime進行保護。
2.需要時應答或重新設定系統時鐘。
3.週期性地使用牆上時間更新實時時鐘。
4.呼叫體系結構無關的時間例程:do_timer().
中斷服務程式主要通過呼叫與體系結構無關的例程do_timer()執行下面的工作:
1.給jiffies_64變數加1.
2.更新資源消耗的統計值,比如當前程序所消耗的系統時間和使用者時間。
3.執行已經到期的動態定時器.
4.執行scheduler_tick()函式.
5.更新牆上時間,該時間存放在xtime變數中.
6.計算平均負載值.

       do_timer看起來還是很簡單的,應為它的主要工作就是完成上面的框架,具體的讓其它函式做就好了:

?
1 2 3 4 5 6 void do_timer(struct pt_regs *regs) { jiffies_64++; update_process_times(user_mode(regs)); update_times(); }

       上述user_mode()巨集查詢處理器暫存器regs的狀態,如果時鐘中斷髮生在使用者空間,它返回1;如果發生在核心模式,則返回0.update_process_times()函式根據時鐘中斷產生的位置,對使用者或對系統進行相應的時間更新:

?
1 2 3 4 5 6 7 8 9 void update_process_times(int user_tick) { struct task_struct *p=current; int cpu=smp_processor_id(); int system=user_tick^1; updata_one_process(p,user_tick,system,cpu); run_local_timers(); scheduler_tick(user_tick,system); }

       update_one_process()函式的作用是更新程序時間。它的實現是相當細緻的。但注意,因為使用了XOR操作,所以user_tick和system兩個變數只要其中有一個為1,則另外一個就必須為0,updates_one_process()函式可以通過判斷分支,將user_tick和system加到程序相應的計數上:

?
1 2 p->utime = user;

相關推薦

linux核心分析筆記----定時時間管理

在這一次裡,主要講講和時間相關的東西,這個我們都比較熟悉,我就直接如主題。       首先要明白兩個概念:系統定時器和動態定時器。週期性產生的事件都是有系統定時器驅動的,這裡的系統定時器是一種可程式設計硬體晶片,它能以固定頻率產生中斷。該中斷就是定時器中斷

(筆記)Linux內核學習(八)之定時時間管理

全局變量 define 結構 load 統計 object 一個 完成 溢出 一 內核中的時間觀念 內核在硬件的幫助下計算和管理時間。硬件為內核提供一個系統定時器用以計算流逝的時間。系 統定時器以某種頻率自行觸發,產生時鐘中斷,進入內核時鐘中斷處理程序中進行

linux核心設計與實現 —— 定時時間管理(第11章)

核心中的時間概念 硬體為核心提供了一個系統定時器用以計算流逝的時間。系統定時器是一種可程式設計硬體晶片,它能以固定頻率產生中斷。該頻率可以通過程式設計預定,稱作節拍率(tick rate)。該中斷就是所謂的定時器中斷,它所對應的中斷處理程式負責更新系統時間,也

Linux核心分析筆記----Page CachePage Writeback

頁快取記憶體是linux核心實現的一種主要磁碟快取,它主要用來減少對磁碟的IO操作,具體地講,是通過把磁碟中的資料快取到實體記憶體中,把對磁碟的訪問變為對實體記憶體的訪問。為什麼要這麼做呢?一,速度;二臨時區域性原理。有關這兩個概念,相信熟悉作業系統的我們不會太陌生。頁快取記憶體是由RAM中的物理頁組

讀書筆記(十一)-定時時間管理

系統中有很多與時間相關的程式(比如定期執行的任務,某一時間執行的任務,推遲一段時間執行的任務),因此,時間的管理對於linux來說非常重要. 主要內容: 系統時間 定時器 定時器相關概念 定時器執行流程 實現程式延遲的方法 定時器和延遲的例子 1.系

Linux Kernel 定時時間管理(淺析)

前言 計算機時間: 這個三維的世界就是由時間,空間,物質構成的,即使是計算機也離不開時間這個東西,時間之於計算機舉足輕重。 計算機的時間 時間管理在核心中佔有很重要的地位。相對於事件驅動而言,核心中有大量的函式都是基於時間驅動的。 這裡先說幾個重要的概念: 相對時間: 假設某

11---定時時間管理

核心中哪些函式需要定期執行? 對排程程式中的佇列進行平衡調整的函式 對螢幕進行重新整理的函式 核心如何計算和管理時間,HZ、節拍和節拍率是什麼? 核心藉助系統定時器計算流失的時間,系統定時器以一定的頻率(預定義,也稱節拍率或HZ)觸發時鐘中斷,核心通過兩次時鐘中斷的間隔計

linux核心分析之軟定時筆記

定時器是一種軟體功能,即允許在將來的某個時刻,函式在給定的時間間隔用完時被呼叫。超時表示與定時器相關的時間間隔已經用完的那個時刻。 linux上考慮兩種型別的定時器,即動態定時和間隔定時器。第一種型別由核心使用,而間隔定時器由程序在使用者態建立。 動態定時器 動態定時的主要

co_routine.cpp/.h/inner.h(第四部分:定時事件迴圈)—— libco原始碼分析、學習筆記

由於本原始碼蠻長的,所以按照功能劃分模組來分析,分為若干部分,詳見二級目錄↑ 定時器和事件迴圈 libco管理定時事件便是使用時間輪這種資料結構 定時器前驅知識本篇只稍微提一下,具體知識請參考《Linux高效能伺服器程式設計 遊雙 著》第11章,或其他方式學

把握linux核心設計思想(七):核心定時定時執行

途】        前面章節說到了把工作推後到除現在以外的時間執行的機制是下半部機制,但是當你需要將工作推後到某個確定的時間段之後執行,使用定時器是很好的選擇。         上一節核心時間管理中講到核心在始終中斷髮生執行定時器,定時器作為軟中斷在下半部上下文中執行。時鐘中斷處理程式會執行update_p

Atitit 定時timer 總結 目錄 1. 定時 迴圈定時 timeout超時定時 1 2. Spring定時 1 2.1. 大概流程 1 2.2. 核心原始碼springboot 1

Atitit 定時器timer 總結   目錄 1. 定時器 迴圈定時器 和timeout超時定時器 1 2. Spring定時器 1 2.1. 大概流程 1 2.2. 核心原始碼springboot 1 3. Js定時器 window.setInte

處理瀏覽器端長時間執行JavaScript指令碼的兩種優化方式:定時worker

第一種:定時器方式,把長時間的任務進行分割成一個數組,間隔一定的時間執行。 function timeProcessArray(items, process, callBack) { let todo = items.concat() setTimeout(function () {

linux核心引數tcp_syn_retries、tcp_retries1tcp_retries2的原始碼分析

enum { TCP_ESTABLISHED = 1, TCP_SYN_SENT, TCP_SYN_RECV, TCP_FIN_WAIT1, TCP_FIN_WAIT2, TCP_TIME_WAIT, TCP_CLOSE, TCP_CLOSE_WAIT,

網易公開課《Linux核心分析》學習心得-Linux核心如何裝載啟動一個可執行程式

實驗 設定斷點sys_execeve,並繼續 程式碼執行到了SyS_execve。在QEMU中執行exec,可以看到只能出現兩句,沒有完全執行完畢。 設定斷點load_elf_binary和start_thread,並執行,可以看到程式碼停在了

《MFC遊戲開發》筆記定時簡單動畫

本系列文章由七十一霧央編寫,轉載請註明出處。       上一節筆記中,我們講解了鍵盤響應和滑鼠響應,實現了對於玩家的操作,程式做出正確的響應。但是大家在玩遊戲的過程中,應該會注意到,在大家沒有操作的時候,程式的畫面仍然不是靜止的,比如NPC會四處走動,怪物仍然會跑過來攻擊玩家等,也就是說,畫面

Atitit 定時timer 總結 目錄 1. 定時 迴圈定時 timeout超時定時 1 2. Spring定時 1 2.1. 大概流程 1 2.2. 核心原始碼springboot 1

Atitit 定時器timer 總結 目錄 定時器 迴圈定時器 和timeout超時定時器 Spring定時器 大概流程 增加一個定時配置類,新增@Configuration和@EnableScheduling註解

Linux核心分析(六):程序的描述程序的建立

一、Linux中的程序簡析 程序是具有多道程式設計的作業系統的基本概念,關於程序的定義就是程式執行的一個例項,也是系統資源排程的最小單位。如果同一個程式被多個使用者同時執行,那麼這個程式就有多個相對獨立的程序,與此同時他們又共享相同的執行程式碼。在Li

linux核心分析--中斷中斷處理程式

寫在前面:       在前面的這篇文章講解了關於中斷的基本概念,從巨集觀的角度瞭解了中斷的基本知識。從這篇文章中要明白幾點知識       1、中斷是由硬體產生的非同步中斷,而異常則是處理器產生的同步中斷       2、中斷質上是一種特殊的電訊號,由硬體裝置發向處理器,

第7節 Linux核心如何裝載啟動一個可執行程式【Linux核心分析

一、實驗要求 分析exec*函式對應的系統呼叫處理過程 二、實驗內容 理解編譯連結的過程和ELF可執行檔案格式,詳細內容參考本週第一節; 程式設計使用exec*庫函式載入一個可執行檔案,動態連結分為可執行程式裝載時動態連結和執行時動態連結,程式設

Linux核心分析Linux核心如何裝載啟動一個可執行程式

1.編譯連結的過程和ELF可執行檔案格式 從一個原始碼檔案到一個可執行程式檔案大概要經歷如下過程: 以C程式碼為例子,有如下程式碼的一個hello.c檔案 //hello.c #include <stdio.h> int ma