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設備驅動開發詳解 宋寶華著
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章