久久婷婷香蕉热狠狠综合,精品无码国产自产拍在线观看蜜,寡妇房东在做爰3,中文字幕日本人妻久久久免费,国产成人精品三上悠亚久久

當前位置:首頁 > 嵌入式培訓 > 嵌入式學習 > 講師博文 > linux中斷(duan)編(bian)(bian)程、中斷(duan)編(bian)(bian)程詳解

linux中斷(duan)編程、中斷(duan)編程詳解(jie) 時間:2018-07-27      來源:未知

Linux中斷(duan)處理驅(qu)動程序(xu)編寫

中斷處(chu)(chu)理是(shi)操(cao)作(zuo)系統必須具(ju)備的上(shang)要功能之(zhi)一(yi),下(xia)面我(wo)們(men)一(yi)起來探討一(yi)下(xia)Linux中的中斷處(chu)(chu)理。

1. 什(shen)么是中斷(duan)

中(zhong)斷(duan)就是(shi)CPU正常運行(xing)期間,由于內、外(wai)部事件引起的(de)CPU暫時停止正在(zai)運行(xing)的(de)程序(xu),去執(zhi)行(xing)該(gai)內部事件或外(wai)部事件的(de)引起的(de)服務中(zhong)去,服務執(zhi)行(xing)完畢(bi)后(hou)再(zai)返回斷(duan)點處繼續執(zhi)行(xing)的(de)情形(xing)。這樣(yang)的(de)中(zhong)斷(duan)機制極大(da)的(de)提高了CPU運行(xing)效率。

1.1. 中(zhong)斷的分類:

1) 根據中(zhong)斷(duan)(duan)的(de)來(lai)源(yuan)可分(fen)為(wei)內(nei)(nei)(nei)部(bu)中(zhong)斷(duan)(duan)和(he)外部(bu)中(zhong)斷(duan)(duan),內(nei)(nei)(nei)部(bu)中(zhong)斷(duan)(duan)的(de)中(zhong)斷(duan)(duan)源(yuan)來(lai)自(zi)于(yu)CPU內(nei)(nei)(nei)部(bu)(軟件(jian)中(zhong)斷(duan)(duan)指令、溢出、除(chu)法(fa)錯誤等),例如(ru)操(cao)作(zuo)系(xi)統從用戶態切換到內(nei)(nei)(nei)核態需要借助CPU內(nei)(nei)(nei)部(bu)的(de)軟件(jian)中(zhong)斷(duan)(duan),外部(bu)中(zhong)斷(duan)(duan)的(de)中(zhong)斷(duan)(duan)源(yuan)來(lai)自(zi)于(yu)CPU外部(bu),由(you)外設觸發。

2) 根據中斷(duan)是否(fou)可(ke)(ke)(ke)以(yi)被屏(ping)蔽,中斷(duan)可(ke)(ke)(ke)分為(wei)可(ke)(ke)(ke)屏(ping)蔽中斷(duan)和不(bu)可(ke)(ke)(ke)屏(ping)蔽中斷(duan),可(ke)(ke)(ke)屏(ping)蔽中斷(duan)可(ke)(ke)(ke)以(yi)通過設(she)置中斷(duan)控(kong)制器(qi)寄存器(qi)等方法被屏(ping)蔽,屏(ping)蔽后,該中斷(duan)不(bu)再得(de)到響應(ying),而不(bu)可(ke)(ke)(ke)屏(ping)蔽中斷(duan)不(bu)能(neng)被屏(ping)蔽。

3) 根據(ju)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan)入(ru)(ru)(ru)(ru)(ru)口(kou)跳(tiao)(tiao)轉方(fang)式的(de)(de)不(bu)同,中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan)可(ke)分(fen)為(wei)向(xiang)量(liang)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan)和非向(xiang)量(liang)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan)。采用向(xiang)量(liang)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan)的(de)(de)CPU通常為(wei)不(bu)同的(de)(de)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan)分(fen)配不(bu)同的(de)(de)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan)號(hao),當檢(jian)測到中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan)的(de)(de)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan)號(hao)到來(lai)時,就自動跳(tiao)(tiao)轉到該中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan)對應的(de)(de)地址(zhi)處(chu)去(qu)執(zhi)行(xing)程(cheng)(cheng)序(xu)。不(bu)同的(de)(de)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan)號(hao)對應不(bu)同的(de)(de)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan)入(ru)(ru)(ru)(ru)(ru)口(kou)地址(zhi)。非向(xiang)量(liang)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan)的(de)(de)多個(ge)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan)共(gong)享一個(ge)入(ru)(ru)(ru)(ru)(ru)口(kou)程(cheng)(cheng)序(xu)處(chu)理(li)入(ru)(ru)(ru)(ru)(ru)口(kou)地址(zhi),中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan)程(cheng)(cheng)序(xu)跳(tiao)(tiao)轉到該入(ru)(ru)(ru)(ru)(ru)口(kou)地址(zhi)執(zhi)行(xing)時,再通過中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan)程(cheng)(cheng)序(xu)來(lai)判斷(duan)(duan)(duan)(duan)(duan)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan)標志來(lai)識別具體是哪一個(ge)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan),也(ye)就是說向(xiang)量(liang)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan)由硬件提(ti)供(gong)(gong)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan)服務(wu)程(cheng)(cheng)序(xu)入(ru)(ru)(ru)(ru)(ru)口(kou)地址(zhi),非向(xiang)量(liang)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan)由軟(ruan)件提(ti)供(gong)(gong)中(zhong)(zhong)(zhong)(zhong)(zhong)斷(duan)(duan)(duan)(duan)(duan)服務(wu)程(cheng)(cheng)序(xu)入(ru)(ru)(ru)(ru)(ru)口(kou)地址(zhi)。

4) 非向量中斷(duan)處理流程:

/*典型(xing)的(de)(de)非向量中(zhong)斷(duan)(duan)(duan)首先會判(pan)斷(duan)(duan)(duan)中(zhong)斷(duan)(duan)(duan)源,然后調用不(bu)同中(zhong)斷(duan)(duan)(duan)源的(de)(de)中(zhong)斷(duan)(duan)(duan)處(chu)理程序*/

irq_handler()

{

...

int int_src = read_int_status();/*讀硬件的(de)中斷相關(guan)寄存器*/

switch(int_src)

{

//判斷中斷標志

case DEV_A:

dev_a_handler();

break;

case DEV_B:

dev_b_handler();

break;

...

default:

break;

}

...

}

2. linux中斷頂部、底部概念

為保證系(xi)(xi)統(tong)實時性,中斷服務(wu)(wu)(wu)程(cheng)(cheng)序(xu)必須(xu)(xu)足(zu)夠簡短,但實際應(ying)用中某(mou)些時候發生中斷時必須(xu)(xu)處理大量的工作,這(zhe)時候如果都在中斷服務(wu)(wu)(wu)程(cheng)(cheng)序(xu)中完成,則會嚴(yan)重(zhong)降(jiang)低中斷的實時性,基(ji)于這(zhe)個原因,linux系(xi)(xi)統(tong)提出了一個概(gai)念:把(ba)中斷服務(wu)(wu)(wu)程(cheng)(cheng)序(xu)分為兩部(bu)分:頂半部(bu)、底半部(bu)。

2.1. 頂(ding)半部(bu)

完成盡(jin)可(ke)能少(shao)的(de)(de)比較急的(de)(de)功能,它往往只是(shi)(shi)簡單的(de)(de)讀(du)取寄存器的(de)(de)中斷(duan)狀(zhuang)態,并(bing)清除中斷(duan)標(biao)志后就(jiu)進(jin)行(xing)“中斷(duan)標(biao)記”(也(ye)就(jiu)是(shi)(shi)把底半部(bu)處理程序掛到(dao)設(she)備的(de)(de)底半部(bu)執行(xing)隊列中)的(de)(de)工作。特點(dian)是(shi)(shi)響應速度快。

2.2. 底半部

中(zhong)斷(duan)(duan)處理的大部(bu)(bu)分工(gong)作(zuo)都在底半部(bu)(bu),它幾乎做了(le)中(zhong)斷(duan)(duan)處理程序的所有事(shi)(shi)情。 特點:處理相對(dui)來說不(bu)是非常(chang)緊急的事(shi)(shi)件 ,底半部(bu)(bu)機制主要有:tasklet、工(gong)作(zuo)隊列和軟(ruan)中(zhong)斷(duan)(duan)。

Linux中(zhong)查看/proc/interrupts文件可以獲(huo)得系統(tong)中(zhong)斷(duan)的(de)統(tong)計信息(xi):

中斷編程

3. Linux中斷編程

3.1. 申請(qing)和釋(shi)放中斷

3.1.1. 申請(qing)中斷:

int request_irq(unsigned int irq,irq_handler_t handler,unsigned long irqflags,const char *devname,void *dev_id);

參數介紹:irq是要申(shen)請的硬件中斷號(hao)。

Handler:是(shi)向(xiang)系(xi)統(tong)登記的中(zhong)斷(duan)處理(li)程(cheng)序(xu)(頂半部),是(shi)一個回(hui)調(diao)函數,中(zhong)斷(duan)發生(sheng)時,系(xi)統(tong)調(diao)用(yong)它,將(jiang)dev_id參(can)數傳遞給它。

irqflags:是中(zhong)斷(duan)處(chu)理的屬(shu)性(xing),可以指定中(zhong)斷(duan)的觸發方式(shi)和處(chu)理方式(shi):

觸(chu)發(fa)方(fang)式:IRQF_TRIGGER_RISING、IRQF_TRIGGER_FALLING、IRQF_TRIGGER_HIGH、IRQF_TRIGGER_LOW,處(chu)(chu)理(li)(li)方(fang)式:IRQF_DISABLE表(biao)明中(zhong)(zhong)斷(duan)(duan)處(chu)(chu)理(li)(li)程序是快速處(chu)(chu)理(li)(li)程序,快速處(chu)(chu)理(li)(li)程序被調用時屏蔽所有中(zhong)(zhong)斷(duan)(duan),IRQF_SHARED表(biao)示多個設備(bei)共(gong)享中(zhong)(zhong)斷(duan)(duan),dev_id在(zai)中(zhong)(zhong)斷(duan)(duan)共(gong)享時會用到,一般設置為NULL。

返回值:為0表示成功(gong),返回-EINVAL表示中斷(duan)號無效,返回-EBUSY表示中斷(duan)已經被占用(yong),且(qie)不(bu)能共享。

頂半部(bu)的handler的類型irq_handler_t定義(yi)為:

typedef irqreturn_t (*irq_handler_t)(int,void*);

typedef int irqreturn_t;

3.1.2. 釋放IRQ

有請(qing)求當然(ran)就有釋放(fang)。中斷(duan)的釋放(fang)函數為:

void free_irq(unsigned int irq,void *dev_id);

參(can)數定義(yi)與request_irq類(lei)似。

3.1.3. 中斷的使能和屏蔽

void disable_irq(int irq);//等待目(mu)前中斷處理完成(最好別在頂板部(bu)使(shi)用,你(ni)懂得)

void disable_irq_nosync(int irq);//立即返回

void enable_irq(int irq);//

3.1.4. 屏蔽(bi)本CPU內所有中斷:

#define local_irq_save(flags)...//禁止中斷并(bing)保存(cun)狀態。

void local_irq_disable(void); //禁止中斷,不保(bao)存(cun)狀態。

下(xia)(xia)面(mian)來分(fen)別(bie)介紹一下(xia)(xia)頂(ding)半(ban)部(bu)和底半(ban)部(bu)的實現機制(zhi)

3.1.5. 底半(ban)部機(ji)制(zhi):

簡介:底半部機制(zhi)主(zhu)要(yao)有tasklet、工作隊列和(he)軟(ruan)中(zhong)斷(duan)

3.1.5.1. 底半部(bu)實現方法之(zhi)一(yi)tasklet

 (1) 我們需(xu)要定(ding)義tasklet機(ji)器處理器并將兩者關(guan)聯,例如:

void my_tasklet_func(unsigned long);/*定義一個處理函數*/

DECLARE_TASKLET(my_tasklet,my_tasklet_func,data);

/*上述代(dai)碼(ma)定義了名為my_tasklet的tasklet并(bing)將(jiang)其與(yu)my_tasklet_func()函數綁定,傳入(ru)的參(can)數為data*/

(2)調度

tasklet_schedule(&my_tasklet);

//使用此(ci)函數就能(neng)在(zai)是(shi)當的時候(hou)進行調度(du)運行

(3)tasklet使用模板:

/*定義(yi)tasklet和底半部函數并關聯*/

void xxx_do_tasklet(unsigned long);

DECLARE_TASKLET(xxx_tasklet, xxx_do_tasklet,0);

/*中斷處理底半部*/

void xxx_do_tasklet(unsigned long)

{

...

}

/*中斷處(chu)理頂(ding)半部*/

irqreturn_t xxx_interrupt(int irq,void *dev_id)

{

...

tasklet_schedule(&xxx_tasklet);//調(diao)度(du)地半部

...

}

/*設(she)備驅動模塊加載(zai)函數*/

int __init xxx_init(void)

{

...

/*申請中斷*/

result = request_irq(xxx_irq,xxx_interrupt, IRQF_DISABLED,"xxx",NULL);

...

return IRQ_HANDLED;

}

/*設(she)備驅動模塊(kuai)卸(xie)載(zai)函(han)數(shu)*/

void __exit xxx_exit(void)

{

...

/*釋(shi)放中(zhong)斷*/

free_irq(xxx_irq,xxx_interrupt);

...

}

 3.1.5.2. 底半部(bu)實現(xian)方(fang)法(fa)之(zhi)二---工(gong)作隊列

使用方(fang)法和(he)tasklet類似,相關操作(zuo):

struct work_struct my_wq;/*定義一個工作隊列*/

void my_wq_func(unsigned long);/*定義一個處理函(han)數*/

通過INIT_WORK()可以(yi)初(chu)始化這個(ge)工(gong)作隊(dui)列(lie)(lie)并(bing)將(jiang)工(gong)作隊(dui)列(lie)(lie)與處理函(han)數綁定(ding)INIT_WORK(&my_wq,(void (*)(void *))my_wq_func,NULL);/*初(chu)始化工(gong)作隊(dui)列(lie)(lie)并(bing)將(jiang)其與處理函(han)數綁定(ding)*/

 schedule_work(&my_wq);/*調度工作隊(dui)列執(zhi)行*/

/*工作隊列(lie)使用模板(ban)*/

/*定義工作隊列和關聯函數*/

struct work_struct(unsigned long);

void xxx_do_work(unsigned long);

/*中斷處(chu)理底半部*/

void xxx_do_work(unsigned long)

{

...

}

/*中斷處理頂(ding)半(ban)部(bu)*/

irqreturn_t xxx_interrupt(int irq,void *dev_id)

{

...

schedule_work(&my_wq);//調度底半部

...

return IRQ_HANDLED;

}

/*設備驅動模塊(kuai)加載函數*/

int xxx_init(void)

{

...

/*申請中斷*/

result = request_irq(xxx_irq,xxx_interrupt,IRQF_DISABLED,"xxx",NULL);

...

/*初始化工作(zuo)隊(dui)列*/

 INIT_WORK(&my_wq,(void (*)(void *))xxx_do_work,NULL);

}

/*設(she)備(bei)驅(qu)動模塊卸載函(han)數*/

void xxx_exit(void)

{

...

/*釋放中(zhong)斷(duan)*/

free_irq(xxx_irq,xxx_interrupt);

...

}

4. 中斷共享(xiang)

中(zhong)(zhong)斷(duan)共享是(shi)指(zhi)多個設(she)備共享一根(gen)中(zhong)(zhong)斷(duan)線的情況,中(zhong)(zhong)斷(duan)共享的使用方法:

(1).在申請中斷時,使(shi)用(yong)IRQF_SHARED標識;

(2).在中(zhong)(zhong)斷到(dao)來時,會(hui)遍歷(li)共享此中(zhong)(zhong)斷的(de)所(suo)有中(zhong)(zhong)斷處理程序(xu),直到(dao)某一(yi)個函(han)數返(fan)回(hui)IRQ_HANDLED,在中(zhong)(zhong)斷處理程序(xu)頂半部中(zhong)(zhong),應迅速根據硬(ying)件寄存器中(zhong)(zhong)的(de)信息參照(zhao)dev_id參數判斷是否為本設備的(de)中(zhong)(zhong)斷,若不是立即返(fan)回(hui)IR1_NONE

/*共享中斷編程模(mo)板*/

irqreturn_t xxx_interrupt(int irq,void *dev_id,struct pt_regs *regs)

{

...

int status = read_int_status();/*獲知(zhi)中斷源*/

if(!is_myint(dev_id,status))/*判斷是否為本設備(bei)中斷*/

return IRQ_NONE;/*不是(shi)本設備中斷,立(li)即返回*/

/*是本(ben)設備中斷,進行(xing)處理*/

...

return IRQ_HANDLED;/*返(fan)回IRQ_HANDLER表(biao)明中斷已經(jing)被(bei)處理*/

}

/*設備模塊加載函數*/

int xxx_init(void)

{

...

/*申請共享(xiang)中斷*/

result = request_irq(sh_irq,xxx_interrupt,IRQF_SHARE,"xxx",xxx_dev);

...

}

/*設備(bei)驅(qu)動(dong)模塊卸載函數*/

void xxx_exit()

{

...

/*釋放(fang)中斷*/

free_irq(xxx_irq,xxx_interrupt);

...

}

5. 內核定時(shi)器

內(nei)核定時器(qi)編程:

簡介:軟件(jian)(jian)意義(yi)上(shang)的定(ding)時(shi)器(qi)最終(zhong)是(shi)依賴于硬件(jian)(jian)定(ding)時(shi)器(qi)實現的,內核在時(shi)鐘中斷(duan)發生后(hou)檢測(ce)各(ge)定(ding)時(shi)器(qi)是(shi)否到(dao)期,到(dao)期后(hou)定(ding)時(shi)器(qi)處(chu)理函數作為軟中斷(duan)在底半部執行。

Linux內(nei)核定時(shi)器操(cao)作:

5.1. timer_list結構體

每一(yi)個timer_list對應一(yi)個定時(shi)器

struct timer_list{

struct list_head entry;/*定時器列表*/

unsigned long expires;/*定(ding)時器到(dao)期時間(jian)*/

void (*function)(unsigned long);/*定(ding)時器(qi)處理函(han)數(shu)*/

unsigned long data;/*作為參數被(bei)傳遞給(gei)定時(shi)器(qi)處(chu)理函(han)數*/

struct timer_base_s *base;

...

};

當定(ding)時器滿的時候,定(ding)時器處(chu)理函數將被執行

5.2. 初(chu)始化定(ding)時器

void init_timer(struct timer_list * timer);

//初始化timer_list的(de)entry的(de)next為NULL,并(bing)給base指針賦值。

TIMER_INITIALIZER(_function,_expires,_data);//此宏(hong)用來

//賦值定時器(qi)結構(gou)體的function、expires、data和base成員

#define TIMER_INITIALIZER(function,_expires,_data)

{

.entry = {.prev = TIMER_ENTRY_STATIC},\

.function= (_function), \

.expires = (_expire), \

.data = (_data), \

.base = &boot_tvec_bases,\

}

DEFINE_TIMER(_name,_function,_expires,_data)//定義一個定時(shi)器結(jie)構(gou)體變量//并為此變量取名(ming)_name

 //還有一(yi)個setup_timer()函數也可以用(yong)于定時器結構體的初始化。

5.3. 增加定時器

void add_timer(struct timer_list * timer);//注冊內核(he)(he)定時(shi)器(qi),也就是將定時(shi)器(qi)加入到內核(he)(he)動態定時(shi)器(qi)鏈表當(dang)中(zhong)。

5.4. 刪除定時器(qi)

del_timer(struct timer_list *timer);

 del_timer_sync()//在刪除(chu)一個定(ding)時器時等待刪除(chu)操作(zuo)被處理完(不能(neng)用于中斷上下文中)

5.5. 修改定(ding)時器expires

int mod_timer(struct timer_list * timer,unsigned long expires);//修改定時器的到期時間

/*內(nei)核定(ding)時器使(shi)用模板*/

/*xxx設備結(jie)構體*/

struct xxx_dev

{

struct cdev cdev;

...

timer_list xxx_timer;/*設備要使用的定時器*/

};

/*xxx驅動中的某函(han)數*/

xxx_funcl(...)

{

struct xxx_dev *dev = filp->private_data;

...

/*初始化(hua)定時器*/

init_timer(&dev->xxx_timer);

dev->xxx_timer.function = &xxx_do_timer;

dev->xxx_timer.data = (unsigned long)dev;

/*設備結構體(ti)指針作為定時器處理函數參(can)數*/

dev->xxx_timer.expires = jiffes + delays;

/*添加(注冊)定時器*/

add_timer(&dev->xxx_timer);

...

}

/*xxx驅(qu)動中的某函數*/

xxx_func2(...)

{

...

/*刪除定(ding)時器*/

del_timer(&dev->xxx_timer);

...

}

/*定(ding)時器處理函數*/

static void xxx_do_timer(unsigned long arg)

{

struct xxx_device *dev = (struct xxx_device *)(arg);

...

/*調度定時器再執行(xing)*/

dev->xxx_timer.expires = jiffes + delay;

add_timer(&dev -> xxx_timer);

...

}

//定時(shi)器到期時(shi)間(jian)往往是在jiffies的基礎上添加一個(ge)時(shi)延(yan),若(ruo)為(wei)HZ則表示(shi)延(yan)遲(chi)一秒

5.6. 內(nei)核(he)中(zhong)的(de)延遲(chi)工(gong)作:

簡介:對(dui)于這(zhe)種周期性的(de)工作(zuo),Linux提供了一套(tao)封裝好的(de)快捷機制,本質上(shang)利用工作(zuo)隊列和定(ding)時(shi)器實現(xian),這(zhe)其(qi)中用到兩個(ge)結構(gou)體:

(1)struct delayed_work

{

struct work_struct work;

struct timer_list timer;

};

(2) struct work_struct

{

atomic_long_t data;

...

}

相關操作:

int schedule_delay_work(struct delayed_work *work,unsigned long delay);//當指定(ding)的delay到來時delay_work中的work成員的work_func_t類(lei)(lei)型成員func()會被執行work_func_t類(lei)(lei)型定(ding)義如下(xia):

typedef void (*work_func_t)(struct work_struct *work);//delay參數(shu)的單位是jiffes

mescs_to_jiffies(unsigned long mesc);//將毫秒轉化成jiffes單位

int cancel_delayed_work(struct delayed_work *work);

 int cancel_delayed_work_sync(struct delayed_work *work);//等待直到刪(shan)除(不(bu)能用于(yu)中(zhong)斷上下文(wen))

內核(he)延遲的相關函數:

短延遲:

Linux內(nei)核提供(gong)了如下(xia)三個函數分別進行納秒、微妙和毫(hao)秒延遲:

void ndelay(unsigned long nsecs);

void udelay(unsigned long usecs);

void mdelay(unsigned long msecs);

機制(zhi):根據CPU頻率進行一(yi)定(ding)次數的循環(huan)(忙等(deng)待)

注意:在Linux內核中(zhong)最好不要使用毫(hao)秒(miao)級的延時,因為這樣會(hui)無謂消耗CPU的資源。

對于毫秒以上(shang)的延時,Linux提供如下函數:

void msleep(unsigned int millisecs);

unsigned long msleep_interruptible(unsigned int millisecs);//可(ke)以被(bei)打斷(duan)

void ssleep(unsigned int seconds);

//上述函數使得調(diao)用它的進程睡眠(mian)指定的時間(jian)

長延遲:

機制:設置(zhi)當(dang)前(qian)jiffies加上時間間隔的jiffies,直到未(wei)來的jiffies達到目標(biao)jiffires

/*實例:先延(yan)(yan)遲100個jiffies再延(yan)(yan)遲2s*/

unsigned long delay = jiffies + 100;

while(time_before(jiffies,delay));

/*再延遲(chi)2s*/

unsigned long delay = jiffies + 2*Hz;

while(time_before(jiffies,delay));//循環直到(dao)到(dao)達(da)指定的時間與timer_before()相(xiang)對應的還有一個time_after

睡著延遲:

睡著(zhu)延遲是比忙等(deng)待更(geng)好的一種(zhong)方法

機制:在等(deng)待的時間到來之(zhi)前(qian)進程處于睡眠狀態,CPU資(zi)源被(bei)其他進程使用(yong),實現函數有:

schedule_timeout()

schedule_timeout_uninterruptible()

其(qi)實(shi)在短延(yan)遲中(zhong)的msleep() msleep_interruptible()

本質上(shang)都是(shi)依(yi)賴于此函(han)(han)數(shu)實現(xian)的,下(xia)面兩個函(han)(han)數(shu)可以讓當(dang)前(qian)進程(cheng)(cheng)加入到(dao)等(deng)待隊列(lie)中,從而在(zai)等(deng)待隊列(lie)上(shang)睡眠,當(dang)超時發生時,進程(cheng)(cheng)被喚醒

 sleep_on_timeout(wait_queue_head_t *q,unsigned long timeout);

 interruptible_sleep_on_timeout(wait_queue_head_t *q,unsigned long timeout);

上一篇:詳解格式化輸入函數scanf

下一篇:Linux應用程序幾種參數傳遞方式

熱點(dian)文章(zhang)推薦
華清學員就業(ye)榜單(dan)
高(gao)薪學員經驗分(fen)享
熱點新聞(wen)推薦
前臺(tai)專線:010-82525158 企業培(pei)訓(xun)洽談(tan)專線:010-82525379 院校合作洽(qia)談(tan)專線:010-82525379 Copyright © 2004-2022 北京華清遠見科技集團有限公司 版權所有 ,,京公海網安備11010802025203號

回到頂部