一、阻塞型I/O
如何使进程进入休眠并在将来唤醒?
对于已经休眠的进程,为了确保唤醒发生,完整唤醒的代码必须找到休眠的进程。所以通过维护一个等待队列的数据结构,可以将需要休眠的进程加入到等待队列中,唤醒的时候通过查找等待队列就能找到需要唤醒的进程。等待队列其实就是一个进程链表,其中包含了等待某个特定事件的所有进程。
1.简单休眠
静态初始化一个等待队列头:
DECLARE_WAIT_QUEUE_HEAD(name);
动态初始化一个等待队列头:
wait_queue_head_t my_queue;
init_waitqueue_head(&my_queue);
休眠函数:
wait_event(queue, condition);
wait_event_interruptible(queue, condition);
wait_event_timeout(queue, condition, timeout);
wait_event_interruptible_timeout(queue, condition, timeout);
以上,queue是等待队列头。使用wait_event进程将被置于非中断休眠。wait_event_interruptible,它可以被信号中断。最后两个版本只会等待限定的时间,时间到期,返回0。
关于唤醒,其他的某个执行线程(可能是另一个进程或者中断处理例程)必须为我们执行唤醒。用来唤醒的函数是wake_up。
void wake_up(wait_queue_head_t *queue);
void wake_up_interruptible(wait_queue_head_t *queue);
wake_up会唤醒等待在给定queue上的所有进程。wake_up_interruptible只会唤醒哪些执行可中断休眠的进程。通常和对应的休眠函数成对使用。
poll和select
poll(轮询)操作在应用程序中用于同时阻塞在多个文件上,当其中任何一个文件有应用程序所等待的事件(可读、可写、出错等)时,poll返回相应的掩码通知应用程序,使得应用程序知道应该对哪个文件做何种操作。
实际上调用poll的进程将会休眠在多个等待队列(一般所有被监控文件描述符都有至少一个的等待队列)上,从其中任何一个队列上唤醒该进程&#x