linux核心分析之軟定時器筆記
定時器是一種軟體功能,即允許在將來的某個時刻,函式在給定的時間間隔用完時被呼叫。超時表示與定時器相關的時間間隔已經用完的那個時刻。
linux上考慮兩種型別的定時器,即動態定時和間隔定時器。第一種型別由核心使用,而間隔定時器由程序在使用者態建立。
動態定時器
動態定時的主要資料結構是一個叫做tvec_bases的per cpu變數,他包含NR_CPUS個元素,系統中每個CPU都有一個。每個元素是一個tvec_base_t型別的資料結構,他包含相應CPU中處理動態定時器需要的所有資料。
struct tvec_base { spinlock_t lock; struct timer_list *running_timer; unsigned long timer_jiffies; unsigned long next_timer; struct tvec_root tv1; struct tvec tv2; struct tvec tv3; struct tvec tv4; struct tvec tv5; } ____cacheline_aligned;
欄位tv1的資料解僱為tvec_root_t型別,包含一個vec陣列,這個陣列由256個list_head元素組成(即256個動態定時器連結串列組成)。這個結構包含了在緊接著到來的255個節拍內將要到期的所有動態定時器。
欄位tv2,tv3和tv4的資料結構都是tvec_t型別,該型別有一個數組vec。這些連結串列包含在緊接著到來的2^14-1/2^20-1以及2^26-1個節拍內將要到期的所有動態定時器。
欄位tv5與前面的欄位幾乎相同,但唯一區別就是vec陣列的最後一項是一個大expires欄位值得動態定時器連結串列。tv5從不需要從其他的陣列補充。
動態定時器程式設計
1,申請timer_list結構並對其初始化,其中必須初始化的有expires,function
struct timer_list { struct list_head entry; unsigned long expires; void (*function)(unsigned long); unsigned long data; struct tvec_base *base; #ifdef CONFIG_TIMER_STATS void *start_site; char start_comm[16]; int start_pid; #endif #ifdef CONFIG_LOCKDEP struct lockdep_map lockdep_map; #endif };
2,呼叫init_timer函式初始化
該函式最終呼叫下面函式
static void __init_timer(struct timer_list *timer,
const char *name,
struct lock_class_key *key)
{
timer->entry.next = NULL;
timer->base = __raw_get_cpu_var(tvec_bases);
#ifdef CONFIG_TIMER_STATS
timer->start_site = NULL;
timer->start_pid = -1;
memset(timer->start_comm, 0, TASK_COMM_LEN);
#endif
lockdep_init_map(&timer->lockdep_map, name, key, 0);
}
可看到初始化的幾個相關變數。
3,呼叫add_timer函式將申請的timer_list結構新增到合適的連結串列
該函式最終呼叫如下函式新增到對應的連結串列
static void internal_add_timer(struct tvec_base *base, struct timer_list *timer)
{
unsigned long expires = timer->expires;
unsigned long idx = expires - base->timer_jiffies;
struct list_head *vec;
if (idx < TVR_SIZE) {
int i = expires & TVR_MASK;
vec = base->tv1.vec + i;
} else if (idx < 1 << (TVR_BITS + TVN_BITS)) {
int i = (expires >> TVR_BITS) & TVN_MASK;
vec = base->tv2.vec + i;
} else if (idx < 1 << (TVR_BITS + 2 * TVN_BITS)) {
int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK;
vec = base->tv3.vec + i;
} else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS)) {
int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK;
vec = base->tv4.vec + i;
} else if ((signed long) idx < 0) {
/*
* Can happen if you add a timer with expires == jiffies,
* or you set a timer to go off in the past
*/
vec = base->tv1.vec + (base->timer_jiffies & TVR_MASK);
} else {
int i;
/* If the timeout is larger than 0xffffffff on 64-bit
* architectures then we use the maximum timeout:
*/
if (idx > 0xffffffffUL) {
idx = 0xffffffffUL;
expires = idx + base->timer_jiffies;
}
i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
vec = base->tv5.vec + i;
}
/*
* Timers are FIFO:
*/
list_add_tail(&timer->entry, vec);
}
其中對於定時器的修改、刪除等操作,核心提供了相應的函式。
相關推薦
linux核心分析之軟定時器筆記
定時器是一種軟體功能,即允許在將來的某個時刻,函式在給定的時間間隔用完時被呼叫。超時表示與定時器相關的時間間隔已經用完的那個時刻。 linux上考慮兩種型別的定時器,即動態定時和間隔定時器。第一種型別由核心使用,而間隔定時器由程序在使用者態建立。 動態定時器 動態定時的主要
Linux核心分析之三——使用gdb跟蹤除錯核心從start_kernel到init程序啟動
作者:姚開健 原創作品轉載請註明出處 《Linux核心分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000 Linux核心(本文以Linux-3.18.6為例)的啟動在原始碼init資料夾裡的main.c
linux核心分析之缺頁中斷
linux缺頁異常程式必須能夠區分由程式設計引起的異常以及由引用屬於程序地址空間但還尚未分配物理頁框的頁所引起的異常。在x86-ia32體系上由do_page_fault函式處理,每個版本有所差異,現分析的版本為2.6.32 /* regs:該結構包含當異常發生時的微處
Linux核心分析之四——系統呼叫的工作機制
作者:姚開健 原創作品轉載請註明出處 《Linux核心分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000 學過計算機作業系統的都知道,CPU工作時有兩種狀態,一種是使用者態,一種是核心態,使用者態意味著
linux核心分析之系統呼叫
在核心入口函式start_kernel中呼叫trap_init實現系統呼叫的初始化工作 void __init trap_init(void) { ... set_system_trap_gate(SYSCALL_VECTOR, &system_call);
Linux核心時間管理和定時器
轉自:http://blog.csdn.net/zhenwenxian/article/details/7643742 時間管理在核心中佔有非常重要的地位。相對於事件驅動,核心中有大量的函式都是基於時間驅動的。核心必須管理系統的執行時間以及當前的日期和時間。 首先搞
linux核心分析之排程演算法(一)
linux排程演算法在2.6.32中採用排程類實現模組式的排程方式。這樣,能夠很好的加入新的排程演算法。 linux排程器是以模組方式提供的,這樣做的目的是允許不同型別的程序可以有針對性地選擇排程演算法。這種模組化結構被稱為排程器類,他允許多種不同哦可動態新增的排程演算法並
Linux核心分析之七——Linux核心如何裝載和啟動一個可執行程式
作者:姚開健 原創作品轉載請註明出處 《Linux核心分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000 1、ELF的檔案格式。 通常我們將程式檔案編譯後得到的目標檔案,在Linux上其格式就是ELF
linux核心分析之rbtree的使用
一、理論基礎 紅黑樹是每個節點都帶有顏色屬性的二叉查詢樹,顏色為紅色或黑色。在二叉查詢樹強制一般要求以外,對於任何有效的紅黑樹我們增加了如下的額外要求: 性質1. 節點是紅色或黑色。 性質2. 根是黑色。 性質3. 所有葉子都是黑色(葉子是NIL節
linux核心設計與實現 —— 定時器和時間管理(第11章)
核心中的時間概念 硬體為核心提供了一個系統定時器用以計算流逝的時間。系統定時器是一種可程式設計硬體晶片,它能以固定頻率產生中斷。該頻率可以通過程式設計預定,稱作節拍率(tick rate)。該中斷就是所謂的定時器中斷,它所對應的中斷處理程式負責更新系統時間,也
linux核心分析筆記----定時器和時間管理
在這一次裡,主要講講和時間相關的東西,這個我們都比較熟悉,我就直接如主題。 首先要明白兩個概念:系統定時器和動態定時器。週期性產生的事件都是有系統定時器驅動的,這裡的系統定時器是一種可程式設計硬體晶片,它能以固定頻率產生中斷。該中斷就是定時器中斷
linux核心程式設計之核心定時器
如果我們需要在將來某個時間點排程執行某個動作,同時在該時間點到達之前不會阻塞當前程序,可以使用核心定時器。核心定時器可用來在未來的某個特定時間點排程執行某個函式,從而可用於完成許多工。 Linux 核心所提供的用於操作定時器的資料結構和函式(位於 <linux/ti
linux驅動開發之蜂鳴器驅動源碼分析(一)
linux 蜂鳴器 驅動 蜂鳴器的驅動源碼在/driver/char/buzzer/x210-buzzer.c文件中,源碼如下#include <linux/module.h> #include <linux/kernel.h> #include <linux
linux音訊alsa驅動分析之三 解碼器
ASoC Codec DriverASoC解碼器驅動 ================= The codec driver is generic and hardware independent code that configures the codec to provide audio capture
linux核心分析--核心中的資料結構之紅黑樹(續)
#include<linux/rbtree.h> #include <linux/string.h> #include "kn_common.h" MODULE_LICENSE("Dual BSD/GPL"); struct student { int id;
linux核心分析--核心中的資料結構之紅黑樹(四)
紅黑樹由於節點顏色的特性,保證其是一種自平衡的二叉搜尋樹。 紅黑樹的一系列規則雖然實現起來比較複雜,但是遵循起來卻比較簡單,而且紅黑樹的插入,刪除效能也還不錯。 所以紅黑樹在核心中的應用非常廣泛,掌握好紅黑樹,即有利於閱讀核心原始碼,也可以在自己的程式碼中借鑑這種資料結構。 紅黑樹必
linux核心分析--核心中使用的資料結構之雜湊表hlist(三)
前言: 1.基本概念: 散列表(Hash table,也叫雜湊表),是根據關鍵碼值(Key value)而直接進行訪問的資料結構。也就是說,它通過把關鍵碼值對映到表中一個位置來訪問記錄,以加快查詢的速度。這個對映函式叫做雜湊函式,存放記錄的陣列叫做散列表。 2. 常用的構造雜湊函式的方法
linux核心分析--核心中的資料結構之佇列(二)
核心中的佇列是以位元組形式儲存資料的,所以獲取資料的時候,需要知道資料的大小。 如果從佇列中取得資料時指定的大小不對的話,取得資料會不完整或過大。 核心中關於佇列定義的標頭檔案位於:<linux/kfifo.h> include/linux/kfifo.h 標頭檔案中定義的函
linux核心分析--核心中的資料結構之雙鏈表(一)
關於核心中使用到的資料結構這一系列會有五篇文章, 分別介紹 連結串列 佇列 雜湊 對映 紅黑樹
Linux核心分析筆記----Page Cache和Page Writeback
頁快取記憶體是linux核心實現的一種主要磁碟快取,它主要用來減少對磁碟的IO操作,具體地講,是通過把磁碟中的資料快取到實體記憶體中,把對磁碟的訪問變為對實體記憶體的訪問。為什麼要這麼做呢?一,速度;二臨時區域性原理。有關這兩個概念,相信熟悉作業系統的我們不會太陌生。頁快取記憶體是由RAM中的物理頁組