微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Linux驱动总结3

Linux驱动总结3

时间:12-01 来源:互联网 点击:

if(_IOC_NR(cmd)>

ioarg = &mem_devp->

condition);当condition为真时,等待队列头queue对应的队列被唤醒,否则继续堵塞。这种情况下不能被信号打断。

wait_event_interruptible(queue,condition);当condition为真时,等待队列头queue对应的队列被唤醒,否则继续堵塞。这种情况下能被信号打断。

4、唤醒等待队列

wait_up(wait_queue_head_t *q),唤醒该等待队列头对应的所有等待。

wait_up_interruptible(wait_queue_head_t *q)唤醒处于TASK_INTERRUPTIBLE的等待进程。

应该成对的使用。即wait_event于wait_up,而wait_event_interruptible与wait_up_interruptible。

wait_event和wait_event_interruptible的实现都是采用宏的方式,都是一个重新调度的过程,如下所示:

#define wait_event_interruptible(wq, condition)

({

int __ret = 0;

if (!(condition))

__wait_event_interruptible(wq, condition, __ret);

__ret;

})

#define __wait_event_interruptible(wq, condition, ret)

do {

/*此处存在一个声明等待队列的语句,因此不需要再重新定义一个等待队列节点*/

DEFINE_WAIT(__wait);

for (;;) {

/*此处就相当于add_wait_queue()操作,具体参看代码如下所示*/

prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);

if (condition)

break;

if (!signal_pending(current)) {

/*此处是调度,丢失CPU,因此需要wake_up函数唤醒当前的进程

根据定义可知,如果条件不满足,进程就失去CPU,能够跳出for循环的出口只有

1、当条件满足时2、当signal_pending(current)=1时。

1、就是满足条件,也就是说wake_up函数只是退出了schedule函数,

而真正退出函数还需要满足条件

2、说明进程可以被信号唤醒。也就是信号可能导致没有满足条件时就唤醒当前的进程。

这也是后面的代码采用while判断的原因.防止被信号唤醒。

*/

schedule();

continue;

}

ret = -ERESTARTSYS;

break;

}

finish_wait(&wq, &__wait);

} while (0)

#define DEFINE_WAIT(name) DEFINE_WAIT_FUNC(name, autoremove_wake_function)

#define DEFINE_WAIT_FUNC(name, function)

wait_queue_t name = {

.private = current,

.func = function,

.task_list = LIST_HEAD_INIT((name).task_list),

}

void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state)

{

unsigned long flags;

wait->flags &= ~WQ_FLAG_EXCLUSIVE;

spin_lock_irqsave(&q->lock, flags);

if (list_empty(&wait->task_list))

/*添加节点到等待队列*/

__add_wait_queue(q, wait);

set_current_state(state);

spin_unlock_irqrestore(&q->lock, flags);

}

唤醒的操作也是类似的。

#define wake_up_interruptible(x) __wake_up(x, TASK_INTERRUPTIBLE, 1, NULL)

void __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);

}

static void __wake_up_common(wait_queue_head_t *q, unsigned int mode,

int nr_exclusive, int wake_flags, void *key)

{

wait_queue_t *curr, *next;

list_for_each_entry_safe(curr, next, &q->task_list, task_list) {

unsigned flags = curr->flags;

if (curr->func(curr, mode, wake_flags, key) &&

(flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)

break;

}

}

等待队列通常用在驱动程序设计中的堵塞读写操作,并不需要手动的添加节点到队列中,直接调用即可实现,具体的实现方法如下:

1、在设备结构体中添加等待队列头,由于读写都需要堵塞,所以添加两个队列头,分别用来堵塞写操作,写操作。

#include

struct mem_dev

{

char *data;

unsigned long size;

/*添加一个并行机制*/

spinlock_t lock;

/*添加一个等待队列t头*/

wait_queue_head_t rdqueue;

wait_queue_head

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top