struct timer_list |-----------------------------------| |struct list_head entry | |unsigned long expires | |void (*function)(unsigned long)| |unsigned long data | |struct tvec_t_base_s *base |--+ |-----------------------------------| -| |void *start_site | -| CONFIG_TIMER_STATS |char start_comm[16]| -| |int start_pid | -| |-----------------------------------| -| | +--------------------------------------+ | 時(shí)鐘向量base結(jié)構(gòu)tvec_t_base_s | struct tvec_t_base_s +-->|---------------------------------| |spinlock_t lock | |struct timer_list *running_timer | |unsigned long timer_jiffies -| base的基準(zhǔn)時(shí)間 |tvec_root_t tv1 | root hash鏈表 |tvec_t tv2 | 二級(jí)hash鏈表 |tvec_t tv3 | 三級(jí)hash鏈表 |tvec_t tv4 | 四級(jí)hash鏈表 |tvec_t tv5 | 五級(jí)hash鏈表 |---------------------------------| ____cacheline_aligned_in_smp expires 定時(shí)器定時(shí)的滴答數(shù)(當(dāng)前的滴答數(shù)為jiffies) function 到那個(gè)時(shí)刻內(nèi)核調(diào)用的函數(shù) data 由于可能多個(gè)定時(shí)器調(diào)用一個(gè)函數(shù),為了使得這個(gè)函數(shù)能夠區(qū)分不同的定時(shí)器,通過(guò)在結(jié)構(gòu)中data來(lái)標(biāo)識(shí)這個(gè)定時(shí)器,并且通過(guò)調(diào)用function(data)使得function能區(qū)分它們,也就是 data起到ID的作用。 使用時(shí)鐘,先聲明一個(gè)timer_list結(jié)構(gòu),調(diào)用init_timer對(duì)它進(jìn)行初始化。 time_list結(jié)構(gòu)里expires是標(biāo)明這個(gè)時(shí)鐘的周期,單位采用jiffies的單位。function就是時(shí)間到了以后的回調(diào)函數(shù),它的參數(shù)就是timer_list中的data。 data這個(gè)參數(shù)在初始化時(shí)鐘的時(shí)候賦值,一般賦給它設(shè)備的device結(jié)構(gòu)指針。在預(yù)置時(shí)間到系統(tǒng)調(diào)用function,同時(shí)系統(tǒng)把這個(gè)time_list從定時(shí)隊(duì)列里清除。所以如果需要一直使用定時(shí)函數(shù),要在function里再次調(diào)用add_timer()把這個(gè)timer_list加進(jìn)定時(shí)隊(duì)列。 管理定時(shí)器的接口 ---------------------------------------------------------- 創(chuàng)建定時(shí)器需要先定義它: struct timer_list my_timer; 接著需要通過(guò)一個(gè)輔助函數(shù)初始化定時(shí)器數(shù)據(jù)結(jié)構(gòu)的內(nèi)部值,初始化必須在使用其他定時(shí)器管理函數(shù)對(duì)定時(shí)器進(jìn)行操作前完成。 init_timer(&my_timer); 現(xiàn)在可以填充結(jié)構(gòu)中需要的值了(與定時(shí)器直接相關(guān)的三個(gè)參數(shù)): my_timer.expires = jiffies + delay; // 定時(shí)器超時(shí)時(shí)的節(jié)拍數(shù) my_timer.data = 0; // 給定時(shí)器處理函數(shù)傳入?yún)?shù)0 my_timer.function = my_function; // 定時(shí)器超時(shí)時(shí)調(diào)用的函數(shù) my_timer.expires表示超時(shí)時(shí)間,它是以節(jié)拍為單位的絕對(duì)計(jì)數(shù)值。如果當(dāng)前jiffies計(jì)數(shù)等于或大于my_timer.expires,那么my_function指向的處理函數(shù)就會(huì)開(kāi)始執(zhí)行,另外該函數(shù)還要使用長(zhǎng)整型參數(shù)my_timer.data。如果你不需要這個(gè)參數(shù),可以簡(jiǎn)單地傳遞0(或任何其他值)給處理函數(shù)。 最后,必須激活定時(shí)器: add_timer(&my_timer); 大功告成,定時(shí)器可以工作了!但請(qǐng)注意定時(shí)值的重要性。當(dāng)前節(jié)拍計(jì)數(shù)大于或等于指定的超時(shí)值時(shí),內(nèi)核就開(kāi)始執(zhí)行定時(shí)器處理函數(shù)。雖然內(nèi)核可以保證不會(huì)在超時(shí)時(shí)間到期前運(yùn)行定時(shí)器處理函數(shù),但是有可能延誤定時(shí)器的執(zhí)行。一般來(lái)說(shuō),定時(shí)器都在超時(shí)后馬上就回執(zhí)行,但是也有可能被推遲到一下時(shí)鐘節(jié)拍才能運(yùn)行,所以不能用定時(shí)器來(lái)實(shí)現(xiàn)任何硬實(shí)時(shí)任務(wù)。 有時(shí)可能需要更改已經(jīng)激活的定時(shí)器超時(shí)時(shí)間,所以內(nèi)核通過(guò)函數(shù)mod_timer()來(lái)實(shí)現(xiàn)該功能,該函數(shù)可以改變指定的定時(shí)器超時(shí)時(shí)間: mod_timer(&my_timer, jiffies+new_delay); mod_timer()函數(shù)也可操作那些已經(jīng)初始化,但還沒(méi)有被激活的定時(shí)器,如果定時(shí)器未被激活,mod_timer()會(huì)激活它。如果調(diào)用時(shí)定時(shí)器未被激活,該函數(shù)返回0;否則返回1。但不論哪種情況,一旦從mod_timer()函數(shù)返回,定時(shí)器都將被激活而且設(shè)置了新的定時(shí)值。 如果需要在定時(shí)器超時(shí)前停止定時(shí)器,可以使用del_timer()函數(shù): del_timer(&my_timer); 被激活或未被激活的定時(shí)器都可以使用該函數(shù),如果定時(shí)器還未被激活,該函數(shù)返回0;否則返回1。注意,你不需要為已經(jīng)超時(shí)的定時(shí)器調(diào)用該函數(shù),因?yàn)樗鼈兂瑫r(shí)后會(huì)自動(dòng)被刪除。 當(dāng)刪除定時(shí)器時(shí),必須小心一個(gè)潛在的競(jìng)爭(zhēng)條件。當(dāng)del_timer()返回后,可以保真的只是: 定時(shí)器不會(huì)再被激活(也就是,將來(lái)不會(huì)執(zhí)行),但是在多處理機(jī)器上定時(shí)器中斷可能已經(jīng)在其他處理器上運(yùn)行了,所以刪除定時(shí)器時(shí)需要等待可能在其他處理器上運(yùn)行的定時(shí)器處理程序都退出,這時(shí)就要使用del_timer_sync()函數(shù)執(zhí)行刪除工作: del_timer_sync(&my_timer); 和del_timer()函數(shù)不同,del_timer_sync()函數(shù)不能在中斷上下文中使用。 tvec_t, tvec_root_t hash鏈表 -- tvec_t_base_s中的hash鏈表 ------------------------------------------------------- --typedef struct tvec_s |------------------------| |struct list_head vec[0] | |------------------------| | | |------------------------| | | |------------------------| | | |------------------------| | | |------------------------| |struct list_head vec[31]| |------------------------| tvec_t typedef struct tvec_root_s |-------------------------| |struct list_head vec[0] -| |-------------------------| | | |-------------------------| | | |-------------------------| | | |-------------------------| | | |-------------------------| |struct list_head vec[128]| |-------------------------| tvec_root_t TVN_SIZE = 32 (or 128) TVR_SIZE = 128 (or 512) ------------------------------------------------------- 根據(jù)內(nèi)核是否配置了CONFIG_BASE_SMALL來(lái)確定向量鏈表數(shù)是32還是128 #define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6) 根據(jù)內(nèi)核是否配置了CONFIG_BASE_SMALL來(lái)確定root鏈表數(shù)是128還是512 #define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8) #define TVN_SIZE (1 << TVN_BITS) #define TVR_SIZE (1 << TVR_BITS) #define TVN_MASK (TVN_SIZE - 1) #define TVR_MASK (TVR_SIZE - 1) boot_tvec_bases ------------------------------------------------------- 定義內(nèi)核時(shí)鐘base全局變量 typedef struct tvec_t_base_s tvec_base_t; tvec_base_t boot_tvec_bases; EXPORT_SYMBOL(boot_tvec_bases); 為每個(gè)CPU定義一個(gè)時(shí)鐘向量基表 static DEFINE_PER_CPU(tvec_base_t *, tvec_bases) = { &boot_tvec_bases }; 就位后的timer和tvec_t_bash_s的關(guān)系視圖 ---------------------------------------------------------- tvec_t_base_s |----------| | | | | | | | | | | | | | | | | | | timer_list timer_list timer_list |----------| |----------| |----------| |----------| | -vec[i] -|<---->|entry |<---->|entry |<---->|entry | |----------| |expires | |expires | |expires | | | |function()| |function()| |function()| | | |data | |data | |data | | | +--|*base | +--|*base | +--|*base | | | | -|----------| | -|----------| | -|----------| | | | | | | | | | | |----------|<--+-----------------+-----------------+ |
聯(lián)系客服