2021-05-12 14:32:11
Linux裝置驅動之定時與延時
2020-06-16 17:26:28
Linux通過系統硬體定時器以規律的間隔(由HZ度量)產生定時器中斷,每次中斷使得一個核心計數器的值jiffies累加,因此這個jiffies就記錄了系統啟動開始的時間流逝,然後核心據此實現軟體定時器和延時。
Demo for jiffies and HZ
#include <linux/jiffies.h>
unsigned long j, stamp_1, stamp_half, stamp_n;
j = jiffies; /* read the current value */
stamp_1 = j + HZ; /* 1 second in the future */
stamp_half = j + HZ/2; /* half a second */
stamp_n = j + n * HZ / 1000; /* n milliseconds */
核心定時器
硬體時鐘中斷處理程式會喚起 TIMER_SOFTIRQ 軟中斷,執行當前處理器上到期的所有核心定時器。
定時器定義/初始化
在Linux核心中,timer_list結構體的一個範例對應一個定時器:
/* 當expires指定的定時器到期時間期滿後,將執行function(data) */
struct timer_list {
unsigned long expires; /*定時器到期時間*/
void (*function)(unsigned long); /* 定時器處理常式 */
unsigned long data; /* function的引數 */
...
};
/* 定義 */
struct timer_list my_timer;
/* 初始化函數 */
void init_timer(struct timer_list * timer);
/* 初始化宏 */
TIMER_INITIALIZER(_function, _expires, _data)
/* 定義並初始化宏 */
DEFINE_TIMER(_name, _function, _expires, _data)
定時器新增/移除
/* 註冊核心定時器,將定時器加入到核心動態定時器連結串列中 */
void add_timer(struct timer_list * timer);
/* del_timer_sync()是 del_timer()的同步版,在刪除一個定時器時需等待其被處理完,
因此該函數的呼叫不能發生在中斷上下文 */
void del_timer(struct timer_list * timer);
void del_timer_sync(struct timer_list * timer);
定時時間修改
int mod_timer(struct timer_list *timer, unsigned long expires);
延時
短延時
void ndelay(unsigned long nsecs);
void udelay(unsigned long usecs);
void mdelay(unsigned long msecs);
核心在啟動時,會執行一個延遲測試程式(delay loop calibration),計算出lpj(loops per jiffy),根據lpj就實現了這幾個函數,屬忙等待。
長延時
-
一個很直觀的方法是比較當前的 jiffies 和目標 jiffies:
int time_after(unsigned long a, unsigned long b); /* a after b, true */ int time_before(unsigned long a, unsigned long b); /* a before b */ int time_after_eq(unsigned long a, unsigned long b); /* a after or equal b */ int time_before_eq(unsigned long a, unsigned long b);/* a before or equal b */
-
睡著延時
void msleep(unsigned int millisecs); unsigned long msleep_interruptible(unsigned int millisecs); void ssleep(unsigned int seconds);
Tip: msleep()、 ssleep()不能被打斷。
本文永久更新連結地址:http://www.linuxidc.com/Linux/2016-12/138133.htm
相關文章