好久沒有提筆寫點東西,最近人有點墮落了。新在的公司老是給我一種養老的感覺。我得自己找點事情乾的,要不這麼年輕就廢了多不好啊。所以就想起提筆寫以下以前的一些學習內核的筆記。有什麼問題望大家指正,大家一起學習。
############ 內核時間 ###############
1、延時
for(i = 0; i < 100; i++);在內核中是不能使用這種延時,在編譯的時候會被優化掉
在內核中使用延時一定要使用內核的API
類似與死循環延時,就是用for封裝的函數
jiffies 是全局變量,用來記錄自系統啓動以來產生的節拍總數
定義在頭文件 <path>/include/linux/jiffies.h
2、短延時:
mdelay()ms級;
udelay()us級;
ndelay()ns級;對與當前的是不支持的,CPU的速度不夠快,以後可能會達到;這個函數存在,但是不>要用,實現時就是mdelay或udelay;
3、長延時:
使用 TIMER4 進行中斷;根據HZ的值來初始化TIMER4,每秒調度器要醒來100次,時間片是10ms
#define HZ #100
unsigned long jiffies //這個變量 1s 加 100 次,
//jiffies 從內核啓動就開始計數,初始值是 -5 * 60 * HZ(-5min);
//jiffies 存的是補碼,這樣就是一個很大的值,+5min就是0了,這樣jiffies 就溢出了,。這樣可
以在你的程序依賴於jiffies時,5min後就會看出效果
int tmp = jiffies + 2 * HZ
while(jiffies < tmp); //xxxxxxx,這是錯的,jiffies是32位的,很容易就溢出了,下面的情況可保>證安全
在延時時間不超過 248.5天的情況:
while(time_before(jiffies, tmp));
while(time_after(jiffies, tmp));
4、睡眠延時:(是放棄cpu睡眠,不是很精確,調度器是10ms才醒來一次,並且調度器的工作也需要消耗時間)
msleep()
ssleep()
set_current_state(狀態)
//函數和程序狀態的宏 --- 頭文件 <include/linux/sched.h>
//這個函數用於設置進程狀態
//TASK_INTERRUPTABLE:代表進程狀態是不可打斷的
schedule_timeout()
//手動啓動調度器,需要手動的設置一下睡眠的狀態
5、內核定時器:(軟件實現的)
timer_list 是基於jiffies實現的
<-******timer_list 內的 func 處理函數是運行在中斷上下文的******->
定時器管理着鏈表的第一個鏈表,放的是還有一次中斷就到期的中斷處理函數(同時到期) jiffies+1
第二個鏈表裏是還有兩次就到期的中斷處理函數jiffies+2
每個中斷到來,內核都會遍歷鏈表,然後把鏈表上掛的任務函數執行,最後把其它鏈表往上提一個,依次類推。
核心頭文件:<path>/include/linux/timer.h
struct timer_list {
struct list_head entry;
unsigned long expires; //到期的時間值;存放這jiffies + 2 * HZ,即 2s 後到期
struct tvec_base *base; //指向維護定時器和做定時器遷移的鏈表
void (*function)(unsigned long); //處理函數
unsigned long data; //作爲上面函數的參數
...
};
函數:
初始化除了結構體中會用到的 3 個(expires、function、data)的,其它全部初始化:
init_timer()
初始化,包括func和data:
setup_timer()
添加一個內核定時器:
add_timer()
相當於修改定時器的值(expires)和add_timer()兩步
mod_timer()
從內核中刪掉定時器:
del_timer()
在多核的時候,會等待其它核把定時器處理函數執行完,這個函數會睡眠:
del_timer_sync()
--->在單核的情況下,這兩個函數是一樣的,所以以後在用的時候都用下面這個就好
這定時器在處理完之後,結構體就會被丟棄;所以想要連續不斷的來定時,在處理函數中再添加一次內核定時
器即可
使用方法:
1:定義一個timer_list
2:init_timer,初始化data,func,expires/setuptimer,初始化expires/mod_timer
3:addtimer 把這個timer加到timer裏
4:創建任務函數實體(func)《有可能睡眠的函數在這裏都不能使用,因爲執行在中斷上下文,不允許>中斷》
5:退出的時候del_timer()註銷定時器
6、獲得當前時間:
do_gettimeofday()
getnstimeofday()
################################################
# 確定必須運行在中斷上下文的是:
# 中斷處理函數
# 軟中斷處理函數
# task_let
# 內核定時器處理函數
################################################