十。內核時間問題

        好久沒有提筆寫點東西,最近人有點墮落了。新在的公司老是給我一種養老的感覺。我得自己找點事情乾的,要不這麼年輕就廢了多不好啊。所以就想起提筆寫以下以前的一些學習內核的筆記。有什麼問題望大家指正,大家一起學習。

############ 內核時間 ###############
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
#   內核定時器處理函數
################################################





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章