- 论坛徽章:
- 0
|
在驱动中因某条件不满足无法为系统调用提供服务时,驱动应采取的策略是将系统调用阻塞,等条件满足之后再返回。那么如何实现阻塞,这就要用内核提供的休眠机制了,即驱动中可以定义多种条件(每种条件对应一个等待队列,每个等待队列需要一个等待队列头),当应用程序使用一些系统调用时,驱动先检查是否可提供服务,当无法提供服务时,将进程加入相应的等待队列头,然后睡眠。
有系统调用遇到驱动无法服务时便调用相关的等待函数:
wait_event(wq, condition)
wait_event_timeout(wq, condition, timeout)
wait_event_interruptible(wq, condition)
wait_event_interruptible_timeout(wq, condition, timeout)
调用之后,此进程因条件不满足而睡眠了,必须由中断或其它进程在修改条件为真之后调用**函数:
wake_up(x)
wake_up_all(x)
wake_up_interruptible(x)
wake_up_interruptible_all(x)
调用之后,内核调度器继续调度该进程(wake_up里到底是怎样做的暂时还没理清头绪,有人知道麻烦告知)
等待函数的实现分析:
wait_event>
__wait_event>
do {/*把当前进程信息填入等待队列项*/ \
DEFINE_WAIT(__wait); \
\
for (; {/*把等待队列项加入等待队列头链表,并设置进程状态*/ \
prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE); \
if (condition) \
break; \
schedule(); \
} \
finish_wait(&wq, &__wait); \
} while (0)
其中的细节还没搞清楚,麻烦大神告知
**函数的实现分析:
__wake_up>
__wake_up_common>
//遍历整个等待队列头链表
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个条件时的示意模板:
static int xxx_read(struct file *filp, char __user *buff,size_t count, loff_t *offp)
{
unsigned long err;
if (条件1) {
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
else
wait_event_interruptible(等待队列头地址, 条件1);//此处睡眠
}
……//条件成立后才能执行到此处,写驱动正常的功能
return ……;
} |
|