《由简至繁》PPT课件.ppt
《《由简至繁》PPT课件.ppt》由会员分享,可在线阅读,更多相关《《由简至繁》PPT课件.ppt(34页珍藏版)》请在三一办公上搜索。
1、1,Chapter 6,時序,2,介紹 由簡至繁,瞭解核心的時序(timing)認識目前時間(current time)將作業的時間點延遲到一定時間之後才開始將非同步函式(asynchronous function)安排到一定時間之後才開始作用,3,6.1 核心的計時間隔,中斷CPU暫停目前工作,然後執行ISR(Interrupt Service Routine)來處理中斷.(CH9)計時器中斷,固定間隔觸發的中斷事件,核心依據HZ(定義在)的值來設定間隔長度,硬體平台不同,值也不同.每次發生計時器中斷,jiffies變數的值就會被遞增一次,宣告在,型別為unsigned long volat
2、ile,核心會確保溢位之後還能正確運作,驅動程式不必擔心jiffies溢位.,4,6.1.1 處理器特有的暫存器,大多數系統上,由於指令時序的不可預測性(因為有指令排程、分支預測、快取記憶體等因素),時脈計數器成為唯一可靠的精密計時工具.時脈計數器的設計隨平台而異,不一定可寫,長度也不一定是32bits或64bits,無論是否可歸零,建議不要如此,因為可以使用無號變數來計算差值.最知名的時脈計數暫存器是x86 Pentium系列的TSC(TimeStamp Counter),為計算CPU時脈週期數的64bits的暫存器,kernel,5,6.1.1 處理器特有的暫存器(Cont.),量測指令本
3、身執行時間 unsigned long ini,end;rdtscl(ini);rdtscl(end);printk(“time lapse:%lin”,end-ini);與平台無關(適用各種平台)的函式用來替代rdstc()#include cycles_t get_cycles(void);/無時脈計數,則回傳TSC暫存器低半段的值,因為可避免多暫存器操作的問題且時脈計數器主要用途為測量極短的時間如何內插組語指令(iniline assembly)將x86的rdtscl()移植到MIPS系統組語指令 Move from coprocessor 0#define rdtscl(dest)_a
4、sm_ _volatile_(“mfc0%0,$9;nop”:“=r”(dest)內插組語的語法相當有威力,但是有點複雜,特別是在那些會限定暫存器用途的平台上(x86系列).完整語法請參考gcc的說明文件.,6,6.2 取得目前時間,在Kernel-space的程式可以從jiffies的值取得目前時間jiffies從開機到至今的時間,與驅動程式生命期無關,也不可能跨越開關機時間.驅動程式可利用jiffies的現值來估算兩事件之間的間隔時間,如mouse driver驅動程式不需要知道牆鐘時刻(wall-clock time),若真的需要靠自己處理當時的時刻,do_gettimeofday()或
5、許可派上用場.此函式並非直接告知今天是星期幾,而是將一般的秒與微秒填入一個struct timeval,原型如下#include void do_gettimeofday(struct timeval*tv);,7,6.2 取得目前時間(Cont.),從xtime變數同樣也可取得目前時刻,但這是不被鼓勵的行為,因為無法連動(atomically)取得timevalue,結構內的tv_sec與tv_usec欄位值,除非暫停掉中斷.若不太講求精準度,2.2版核心提供一個快又安全的函式來取得目前時刻:void get_fast_time(struct timeval*tv);範例 jit(Just
6、In Time)模組,它不會產生裝置節點,而是直接將它取得的時刻資訊透過/proc/currentime傳到user-space.,cat/proc/currentime/proc/currentime/proc/currentime,8,6.3 延遲執行,驅動程式通常需要拖延某段程式碼的開始執行時間通常是為了讓硬體有足夠充裕的時間完成某些工作需要考慮的重點之一,是延遲時間是否超過一個時脈單位較長的延遲,可以利用系統時鐘來計時,較短的延遲,則通常以軟體迴圈來應付,9,6.3.1 長期延遲(1/4),最簡單也是最蠢的做法,稱為忙著等待(busy waiting):unsigned long j=
7、jiffies+jit_delay*HZ;while(jiffies j)/*發呆*/;因為jiffies是volatile變數,使得C編譯器會落實每次的讀取動作(不使用快取技術).在延遲期間,處理器是被鎖死的,因為這是核心裡的迴圈,排程器不會岔斷進入核心的行程.若中斷失效時進入迴圈,jiffies就不會被更新,迴圈也將無法終止,此時只能使用reset按鈕.,10,6.3.1 長期延遲(2/4),busy-wait範例,讀取/proc/jitbusy,每當它的read作業方法被呼叫一次,其內部的忙碌迴圈就會延遲一秒.如果使用dd if=/proc/jitbusy bs=1命令,就可以看到每秒讀
8、出一個字元的效果.這種做法會嚴重拖累系統效能,因為其他行程每隔一秒才有機會執行一次,比較合理的做法是:while(jiffies j)schedule();但還不夠理想,倘若它是整個系統上唯一的可跑行程,它真的會動作(呼叫schedule(),然後立刻被排程器選中,然後再呼叫schedule()所以說,機器負載程度將至少等於1,而idle行程將沒機會上線.由於在延遲時間,行程其實還在跑,所以它所耗的時間算在該行程上,由下列指令來證實。若在一個非常忙碌的系統上,呼叫排程器的做法,反而有可能造成驅動程式等待了超過原本預期的時間.,time cat/proc/jitsched,11,6.3.1 長期
9、延遲(3/4),排程迴圈提供一個觀測驅動程式工作程序的速成工具.(printk()之後一點點延遲,讓klogd有機會盡忠職守,以免不知如何死當)最佳的延遲方式,是要求核心代勞,核心提供兩種執行短程延遲的機制,看你的驅動程式是否要等待其他事件而定.sleep_on_timeout(wait_queue_head_t*q,unsigned long timeout);interruptible_sleep_on_timeout(wait_queue_head_t*q,unsigned long timeout);兩種版本都會讓行程待在指定的待命佇列裡休眠,但一定會在指定期限內返回.timeout值
10、是要等待的jiffies個數,而非jiffies絕對值.,12,6.3.1 長期延遲(4/4),範例/proc/jitqueue wait_queue_head_t wait;init_waitqueue_head(但實際延遲時間,有可能略為超過你原本預期的時間.,time cat/proc/jitqueue,time cat/proc/jitself,13,6.3.2 短期延遲,在計算非常短暫的延遲,jiffies無法達成,所以核心提供udelay()和mdelay()函式,原型如下:#include void udelay(unsigned long usecs);/inline void
11、 mdelay(unsigned long msecs);udelay()以當地系統的BogoMips(開機所計算出的系統常數)值來決定迴圈的圈數,其值大約是CPU時脈速的兩倍左右.mdelay()是含有udelay()的迴圈所構成兩者都是busy-waiting函式,因此除非沒有其他辦法,否則應該儘量避免使用mdelay(),14,6.4 工作佇列(Task Queue),驅動程式都需要的能力為不倚賴中斷機制的前提下,將某些工作安排到一段時間之後才開始執行.Linux有三種介面,分別是工作佇列、tasklet(2.3.43)以及核心計時器工作佇列和tasklet是安排工作執行時機的工具,最常
12、被應用在interrupt handler.而核心計時器是用來將工作安排到未來的特定時間才執行.本節先說明工作佇列,然後介紹核心提供的現成工作佇列,以及如何觸發驅動程式自己產生的工作佇列,最後看看新玩意tasklet介面.,15,6.4.1 工作佇列的本質,由task構成的串列,每一個工作都是以一個函式指標與一個引數的組合來表示.當工作開始跑時,它會收到一個void*引數,並傳回void.指標引數可用來傳遞資料結構給工作函式,也可以被忽略.下列結構描述引述自 struct tq_struct struct list_head list;/*linked list of active bhs*/
13、unsigned long sync;/*must be initialized to zero*/void(*routine)(void*);/*function to call*/void*data;/*argument to function*/bh代表bottom half(interrupt handler的後半段),目前只要知道它是為了處理非同步工作所提供的機制.(Ch9),16,6.4.1 工作佇列的本質(Cont.),核心利用sync旗標來避免將同一工作重複排在多個佇列裡,因為會破壞到next指標.另一種資料結構是task_queue,它目前只是一個指向struct tq_st
14、ruct的指標,task_queue指標必須先初始化成NULL才能使用.以下是用來操作tq_struct和工作佇列的工具:DECLARE_TASK_QUEUE(name);此巨集宣告一個名為name的工作佇列,並清空它 int queue_task(struct tq_struct*task,task_queue*list);將工作排入佇列,若工作已存在則傳回0,成功則傳回非零值.void run_task_queue(task_queue*list);用來消化指定佇列中的累積工作,你不必直接呼叫,除非你宣告並維護自己的工作佇列.,17,6.4.2 工作佇列的運作原理,工作佇列何時開工?當核心
15、空閒時。不同種類的佇列,各有不同的開工時機。工作佇列時常被當成軟體中斷的處理機制,在中斷模式執行程式碼,能力受到一些限制,必須嚴格遵守下列規矩:不容許存取user-space.因為沒有行程環境,所以沒有辦法接觸到任何特定行程的user-space.在中斷模式下,current指標是無效的,而且也不能使用.不能休眠,也不能要求排程,也不能使用其他可能被催眠的函數,如呼叫kmalloc將違反本規矩或使用權狀(semaphore)等,因為在等待別人讓出權狀的過程中,你會被催眠.核心程式如何得知自己是否處於中斷模式下?使用in_interrupt(),若傳回非零值,表示處理器正處於中斷模式.2.4版核
![《由简至繁》PPT课件.ppt_第1页](https://www.31ppt.com/fileroot1/2023-5/20/74f30c00-409c-4ebd-a45f-4ee00446cd68/74f30c00-409c-4ebd-a45f-4ee00446cd681.gif)
![《由简至繁》PPT课件.ppt_第2页](https://www.31ppt.com/fileroot1/2023-5/20/74f30c00-409c-4ebd-a45f-4ee00446cd68/74f30c00-409c-4ebd-a45f-4ee00446cd682.gif)
![《由简至繁》PPT课件.ppt_第3页](https://www.31ppt.com/fileroot1/2023-5/20/74f30c00-409c-4ebd-a45f-4ee00446cd68/74f30c00-409c-4ebd-a45f-4ee00446cd683.gif)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 由简至繁 简至繁 PPT 课件
![提示](https://www.31ppt.com/images/bang_tan.gif)
链接地址:https://www.31ppt.com/p-5638601.html