Linux设备驱动中的阻塞与非阻塞I/O

Linux设备驱动中的阻塞与非阻塞I/O

本文从两个方面进行阐述阻塞与非阻塞、等待队列、轮询机制;

1. 阻塞与非阻塞

1.1 阻塞与非阻塞概念

阻塞:在执行设备操作时,当资源被占用,进程将被挂起处于休眠状态,同时将从调度器的运行队列中移走,直至等待的条件满足时,才用中断来进行唤醒,否则将无法继续执行。
非阻塞:当执行设备操作时,当资源被占用无法获取时,或者立即返回,或者轮询等待,对cpu是一种不断的消耗。

1.2 等待队列

等待队列是用来对阻塞的唤醒机制,同时与进程调度机制相结合,实现异步事件的通知机制。
等待队列的基本操作:

1)定义“等待队列头”
wait_queue_head_t my_queue;

<strong>2) 初始化等待队列头</strong>
init_waitqueue_head(&my_queue);

<strong>3)定义等待队列</strong>
DECLEARE_WAITQUEUE(name, tsk);

<strong>4)添加/删除等待队列</strong>
void fastcall add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);
void fastcall remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);

<strong>5)等待事件</strong>
wait_event(queue, condition);
wait_event_interruptible(queue, condition);
wait_event_timeout(queue, condition);
wait_event_interruptible_timeout(queue, condition);

<strong>6)唤醒队列</strong>
与等待队列成对使用
void wake_up(wait_queue_head_t *queue);
void wake_up_interruptible(wait_queue_head_t *queue);

<strong>7)等待队列上睡眠</strong>
sleep_on(wait_queue_heat_t *q);
interruptible_sleep_on(wait_queue_head_t *q);

在驱动程序中改变进程状态并调用schedule代码实例:
static ssize_t xxx_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
	...
	<strong>DECLEARE_WAITQUEUE(wati, current);	/*定义等待队列*/
	add_wait_queue(&xxx_wait, &wait);	/*添加等待队列*/</strong>

	ret = count;
	/*等待设备缓冲区可写*/
	do
	{
		avail = device_writable(...);
		if(avail < 0)
		<strong>__set_current_state(TASK_INTERRUPTIBLE);	/*改变进程状态*/</strong>
		
		if(avail < 0)
		{<strong>
</strong>			if(file->f_flags * O_NONBLOC)  /*非阻塞*/
			{
				if(!ret)
					ret = - EAGAIN;
					goto out;
			}
			
			<strong>schedule();	/*调度其它进程*/
			if(signal_pending(current) )	/*如果是因为信号量唤醒*/</strong>
			{
				if(!ret)
				{
					ret = - ERESTARTSYS;
					goto out;
				}
			}
		}
	}while (avail < 0)
	
	/*写设备缓冲区*/
	device_write(...);
	out:
	<strong>remove_wait_queue(&xxx_wait, &wait);	/*将等待队列移出等待队列头*/
	set_current_state(TASK_RUNNING);	/*设置进程状态*/</strong>
	return ret;	
}

1.3 阻塞与非阻塞实例
2. 轮询机制

使用非阻塞IO的应用程序通过使用select()和poll()对设备进行非阻塞的访问。

3. 总结

阻塞与非阻塞是IO操作的两种方式,阻塞通过等待队列来实现,而非阻塞在应用程序层通过select()和poll()来实现,在驱动层通过poll来实现。

4.参考文献

1)Linux设备驱动开发详解 宋宝华著
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值