设备驱动之一 - 手工休眠
进程休眠步骤可通过手工设置:
1. 创建和初始化一个等待队列。常由宏定义完成:
DEFINE_WAIT(my_wait);
其中的name 是等待队列入口项的名字. 当然也可以用2步来做:
wait_queue_t my_wait;
init_wait(&my_wait);
常用的做法是放一个 DEFINE_WAIT 在循环的顶部,来实现休眠。
2. 添加等待队列入口到队列,并设置进程状态:
void prepare_to_wait(wait_queue_head_t *queue,
wait_queue_t *wait,
int state);
queue 和 wait 分别地是等待队列头和进程入口。
state 是进程的新状态:TASK_INTERRUPTIBLE(可中断休眠,推荐)或TASK_UNINTERRUPTIBLE(不可中断休眠,不推荐)
3. 在检查确认仍然需要休眠之后调用 schedule
if (!condition)
schedule( ); /*调用调度器,并让出CPU*/
4. 清理,schedule 返回,就到了清理时间:
void finish_wait(wait_queue_head_t *queue, wait_queue_t *wait);
其实wait_event(queue, condition) 和 wait_event_interruptible(queue, condition) 底层源码也只是手工休眠中的函数的组合。
所以怕麻烦的话还是用wait_event比较好。
linux设备驱动中的实例:
static int scull_getwritespace(struct scull_pipe *dev, struct file *filp)
{
while (spacefree(dev) == 0) { /* 判断缓冲区是否为NULL */
/* 创建和初始化一个等待队列 */
DEFINE_WAIT(wait);
up(&dev->sem);
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
PDEBUG("\"%s\" writing: going to sleep\n",current->comm);
/* 添加等待队列入口到队列,并设置进程状态TASK_INTERRUPTIBLE */
prepare_to_wait(&dev->outq, &wait, TASK_INTERRUPTIBLE);
/* 在检查确认仍然需要休眠之后调用 schedule */
if (spacefree(dev) == 0)
schedule();
/* 执行清理操作 */
finish_wait(&dev->outq, &wait);
if (signal_pending(current))
return -ERESTARTSYS; /* signal: tell the fs layer to handle it */
if (down_interruptible(&dev->sem))
return -ERESTARTSYS;
}
return 0;
}
posted on 2012-07-26 22:24 YoungerChina 阅读(223) 评论(0) 收藏 举报
浙公网安备 33010602011771号