阻塞和非阻塞IO

来源:互联网 发布:淘宝卖家服务助手 编辑:程序博客网 时间:2024/04/27 10:16


用户空间需要从设备读入数据或写入数据到设备时,由于外部设备与CPU相比速度慢很多,内核接收到读/写命令后,需要等待一段时间才能从设备输入相关的数据或把数据写到设备中;这时系统可以把用户线程设为休眠状态,cpu资源让给其他的线程使用。当设备已经将数据处理好了,再把结果返回用户线程,重新把用户线程设为运行状态。这种IO方式就是阻塞型的IO

相反,如果读写操作时,不阻塞用户线程的运行,即使没有准备好设备的数据,都立即把命令执行结果返回给用户线程,这叫做非阻塞型IO


非阻塞型IO用户线程调用时通过设置O_NONBLOCK标志(或O_NDELAY标志)实现,内核代码检测到这个标志,这时即使没有可读的数据,也立即返回。


阻塞型IO

阻塞型IO使用户线程进行休眠的过程:

1)创建一个wait_queue_t结构体,将线程的相关信息保存到这个结构体中,同时把wait_queue_t放入wait_queue_head_t队列中,也就是放入休眠队列

2)设置线程的运行状态,由TASK_RUNNING改为TASK_INTERRUPTIBLE或TASK_UNINTERRUPTIBLE,然后调用schedule()函数,将线程调度出运行队列

3)进行休眠前的清理工作


使用方法:

1)定义变量并进行初始化

DECLARE_WAIT_QUEUE_HEAD(my_quehead);


wait_queue_head_t my_quehead;

init_waitqueue_head(my_quehead);

2)阻塞函数

wait_event(wq, condition);

wait_event_timeout(wq, condition, timeout);

wait_event_interruptible(wq, condition);

wait_event_interruptible_timeout(wq, condition, timeout);

wq是内核希望将线程送入的休眠队列,condition是进入休眠和退出休眠的条件,timeout表示在timeout时间内还没有激活,则自动激活,并推出休眠。

interruptible表示是可中断的,否则不可中断,只能通过wake_up进行激活

2)激活函数

wake_up(x)

wake_up_interruptible(x)


上述wait_event和wake_up函数其实是调用

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

函数实现的,我们也可以手动调用这些函数实现阻塞型IO操作

具体内容参考<linux/wait.h>头文件







原创粉丝点击