阻塞与非阻塞

LINUX设备文件高级操作之阻塞与非阻塞IO
一 阻塞与非阻塞IO
 
阻塞操作:在进行设备文件操作的时候,如果不能获得资源(操作条件没有被满足),则挂起进程(休眠)直到满足可操作的条件为止。
 
非阻塞操作:在进行设备文件操作的时候,如果不能获得资源(操作条件没有被满足),进程不被挂起,而是放弃操作或者不停地查询知道满足操作条件为止。
 
对与阻塞与非阻塞的最简单操作就是以阻塞/非阻塞
方式 读/写
文件,实例代码如下:
 
以阻塞方式读文件:
fd
= open(“/dev/stty1”,O_RDWR)
res
= read(fd,&buf,1);
用这种方式读文件,只有当stty1设备有输入时read才能返回。
 
以非阻塞方式读文件:
fd
= open(“/dev/stty1”,O_RDWR | O_NONBLOCK);
while(read(fd,&buf,1));
用这种方式读文件,当stty1设备没有输入时,也能返回。(所以要不停地查询设备)
 
二 等待队列
等待队列的组成有:等待队列头和等待队列节点。
 
1
等待队列头的定义如下:
 
struct
__wait_queue_head {
	spinlock
lock;
	struct
list_head task_list;
};
 
spinklock
lock是一个自选锁,用于防止等待队列被并发访问(当然不能同时唤醒两次或者睡眠两次)。
task_list是用来组织等待队列节点成为链表的指针。
 
2
等待队列节点的定义如下:
 
struct
__wait_queue {
	unsigned
int flag ;
	void
*private;
	wait_queue_fuc_t
fuc;
	struct
list_head task_list;
}
 
 unsigned
int flag 排他标志。(在唤醒等待队列时,如果等待队列设置了排他性,那么唤醒动作将在唤醒一个设置了排他性标志的进程后停止)
 
private
私有数据。实际使用中指向了该节点上的task_struct
 
Fuc
当该节点上的进程需要被唤醒时执行的唤醒函数。初始化时被设置成为默认唤醒函数。
 
task_list
用于组织队列的指针。
 
 
基于等待队列头和等待队列节点,阻塞与非阻塞动作可以更加复杂。
其具体设置思想是:当进程A对设备文件的操作条件没有被满足时,进程A被挂在一个等待队列节点上,并且加入一个等待队列当中(由等待队列头组织起来的许多等待队列节点),然后设置睡眠。
 
设置睡眠的方式用一下几种:
 
1
全权把握:首先调用__set_current_state函数设置当前进程的状态为睡眠,然后启动调度
。
2
等待事件睡眠:调用wait_event_xxxqueue,condiction)宏。等待条件满足。
			wait_event_intrruptable
			wait_event_timeout
			wait_event_interruptable_timerout
3
在队列上直接休眠:调用函数
sleep_on,该函数实际上是讲进程设置为TASK_UNINTERRUPTABLE然后设置一个等待队列节点用于挂接进程,接着将该节点挂到等待队列上,然后调用带超时的调度器:schedule_timeout进行进程调度。
 
note:一个将要睡眠的进程必须挂接到一个等待队列上,因为唤醒操作是以等待队列为单位进行的。
 
三 轮询
在用户空间调用poll会引发系统调用最终调用到驱动fops结构体当中的poll函数。
也就是说我们必须自己实现驱动当中的poll函数。Poll函数做的事情有:
1
将文件几个文件描述符放入文件描述符集中。
2
扫描每个文件并且调用文件当中的.poll函数,并且对mask设置以通知用户程序读写情况和原因。
3
当文件可读写时,.poll函数返回1
,并count++
。否则返回0
4
循环结束后判断count,若为0则睡眠,直到被唤醒。若为!0则直接返回count
 
Note:
既然poll机制涉及睡眠那就必须涉及到等待队列和等待队列节点。并且这个等待队列由设备文件的驱动程序来维护。在设备驱动中调用这个函数:poll_waitstruct
file *flip,wait_queue_head *queue,poll_table
*wait)这个函数将等待队列加入了poll_table
*wait这个列表当中,进行维护。当返回mask0时,就将wait列表当中的等待队列统统设置为休眠状态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值