linux下如何阻塞进程

来源:互联网 发布:2017程序员薪资报告 编辑:程序博客网 时间:2024/05/22 04:26
提出问题:若驱动程序无法立即满足请求,该如何响应? 比如:当数据不可用时调用read,或是在缓冲区已满时,调用write
解决问题:驱动程序应该(默认)该阻塞进程,将其置入休眠状态直到请求可继续。

休眠:

当一个进程被置入休眠时,它会被标记为一种特殊状态并从调度器运行队列中移走,直到某些情况下修改了这个状态,才能运行该进程。
安全进入休眠两原则:
1.永远不要在原子上下文中进入休眠。(原子上下文:在执行多个步骤时,不能有任何的并发访问。这意味着,驱动程序不能再拥有自旋锁,seqlock,或是RCU锁时,休眠)
2.对唤醒之后的状态不能做任何假定,因此必须检查以确保我们等待的条件真正为真

临界区  vs  原子上下文
原子上下本:一般说来,具体指在中断,软中断,或是拥有自旋锁的时候。
临界区:每次只允许一个进程进入临界区,进入后不允许其它进程访问。

other question:
要休眠进程,必须有一个前提:有人能唤醒进程,而起这个人必须知道在哪儿能唤醒进程,这里,就引入了“等待队列”这个概念。
等待队列:就是一个进程链表(我的理解:是一个休眠进程链表),其中包含了等待某个特定事件的所有进程。
等待队列头:wait_queue_head_t,定义在<linux/wait.h>
定义方法:静态  DECLARE_QUEUE_HEAD(name)
                      动态  wait_queue_head_t  my_queue;
                                 init_waitqueue_head(&my_queue);

struct __wait_queue_head {
    spinlock_t lock;
    struct list_head task_list;
};
typedef struct __wait_queue_head wait_queue_head_t;

简单休眠
linux最简单的休眠方式是wait_event(queue,condition)及其变种,在实现休眠的同时,它也检查进程等待的条件。四种wait_event形式如下:
wait_event(queue,condition);/*不可中断休眠,不推荐*/
wait_event_interruptible(queue,condition);/*推荐,返回非零值意味着休眠被中断,且驱动应返回-ERESTARTSYS*/
wait_event_timeout(queue,condition,timeout);
wait_event_interruptible_timeout(queue,conditon,timeout);/*有限的时间的休眠,若超时,则不管条件为何值返回0*/

唤醒休眠进程的函数:wake_up
void wake_up(wait_queue_head_t  *queue);
void wake_up_interruptible(wait_queue_head  *queue);