新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > arm驅(qū)動(dòng)linux等待隊(duì)列阻塞中斷IO的應(yīng)用

arm驅(qū)動(dòng)linux等待隊(duì)列阻塞中斷IO的應(yīng)用

作者: 時(shí)間:2016-11-19 來(lái)源:網(wǎng)絡(luò) 收藏
《[arm驅(qū)動(dòng)]linux等待隊(duì)列阻塞中斷IO的應(yīng)用》涉及內(nèi)核驅(qū)動(dòng)函數(shù)四個(gè),內(nèi)核結(jié)構(gòu)體零個(gè),分析了內(nèi)核驅(qū)動(dòng)函數(shù)四個(gè);可參考的相關(guān)應(yīng)用程序模板或內(nèi)核驅(qū)動(dòng)模板一個(gè),可參考的相關(guān)應(yīng)用程序模板或內(nèi)核驅(qū)動(dòng)一個(gè)

一、概念:
要休眠進(jìn)程,必須有一個(gè)前提:有人能喚醒進(jìn)程,而起這個(gè)人必須知道在哪兒能喚醒進(jìn)程,這里,就引入了“等待隊(duì)列”這個(gè)概念。
二、應(yīng)用場(chǎng)景:
等待隊(duì)列用來(lái)實(shí)現(xiàn)進(jìn)程的阻塞,等待隊(duì)列可看作保存進(jìn)程的容器,在阻塞進(jìn)程時(shí),將進(jìn)程放入等待隊(duì)列,當(dāng)喚醒進(jìn)程時(shí),從等待等列中取出進(jìn)程。進(jìn)程進(jìn)入休眠后必須有個(gè)地方能夠喚醒休眠的進(jìn)程;喚醒進(jìn)程的地方最大可能是中斷里面,應(yīng)為硬件資源的獲取的同時(shí)往往伴隨著一個(gè)中斷。所以在中斷中常常使用等待隊(duì)列來(lái)休眠進(jìn)程,將cpu資源讓給其他進(jìn)程,中斷發(fā)生時(shí)喚醒進(jìn)程
三、中斷休眠相關(guān)函數(shù)
1、生成等待事件的函數(shù)

本文引用地址:http://m.butianyuan.cn/article/201611/318222.htm

內(nèi)核函數(shù)一)a)函數(shù)wait_event_interruptible(queue,condition)函數(shù)

wait_event_interruptible(queue,condition) //當(dāng)condition(一個(gè)布爾表達(dá)式)為真時(shí),立即返回;
//否則讓進(jìn)程進(jìn)入TASK_INTERRUPTIBLE的睡眠,并掛在名為queue所指定的等待隊(duì)列上。

內(nèi)核代碼一)b)內(nèi)核代碼

#define wait_event_interruptible(wq, condition)
({
int __ret = 0;
if (!(condition))
__wait_event_interruptible(wq, condition, __ret);
__ret;
})

內(nèi)核函數(shù)二)2、wake_up_interruptible(queue);//喚醒隊(duì)列中的名為queue的隊(duì)列
內(nèi)核代碼二)a)內(nèi)核源碼

#define wake_up_interruptible(x) __wake_up(x, TASK_INTERRUPTIBLE, 1, NULL)
void fastcall __wake_up(wait_queue_head_t *q, unsigned int mode,
int nr_exclusive, void *key)
{
unsigned long flags;
spin_lock_irqsave(&q->lock, flags);
__wake_up_common(q, mode, nr_exclusive, 0, key);
spin_unlock_irqrestore(&q->lock, flags);
}

3、定義隊(duì)列名為queue的兩種方法
內(nèi)核函數(shù)三)a)靜態(tài)定義方法: DECLARE_QUEUE_HEAD(name)(常用)
內(nèi)核代碼三)內(nèi)核代碼

#define DECLARE_WAIT_QUEUE_HEAD(name) wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
#define __WAIT_QUEUE_HEAD_INITIALIZER(name) {
.lock = __SPIN_LOCK_UNLOCKED(name.lock),
.task_list = { &(name).task_list, &(name).task_list } }

內(nèi)核函數(shù)四)b)動(dòng)態(tài)定義方法:

wait_queue_head_t my_queue;
init_waitqueue_head(&my_queue);

內(nèi)代碼四)內(nèi)核代碼

init_waitqueue_head(&my_queue)的內(nèi)核代碼
void init_waitqueue_head(wait_queue_head_t *q)
{
spin_lock_init(&q->lock);
INIT_LIST_HEAD(&q->task_list);
}

三、等待隊(duì)列代碼使用參考模板

模板一)

staticDECLARE_WAIT_QUEUE_HEAD(queue);
staticintflag =0;
staticirqreturn_t irq_handle(intirq, void*dev__id){
//printk("irq = %dn", irq);
//..........其他代碼.............
flag = 1;
wake_up_interruptible(&queue);
returnIRQ_RETVAL(IRQ_HANDLED);//warn:榪斿洖IRQ_HANDLED
}
ssize_t XXXXX_read(structfile *filp,char__user *buf,size_tcount,loff_t *pos)
{
//pirntk(KERN_DEBUG "process %i (%s) going to sleepn",current->pid,current->comm);
wait_event_interruptible(queue,flag);//此時(shí)進(jìn)程被加入等待隊(duì)列,等待中斷發(fā)生
flag=0;
//printk(KERN_DEBUG "awoken %i (%s) n",current->pid,current->comm);
returncount;//這個(gè)count變量看自己需要更改
}



評(píng)論


技術(shù)專區(qū)

關(guān)閉