在linux驅動中,有時候需要實現非阻塞的read和write操作,但用戶不可能週期地去查詢設備是否可讀或可寫吧,那在驅動中就需要實現poll接口,然後在應用層調用select系統調用。
在驅動中需要實現poll接口,其主要內容爲通過poll_wait(讀等待隊列,wait)、poll_wait(寫等待隊列)將讀、寫等待隊列添加到wait表中。注意:poll_wait()本身並不是阻塞的調用,真正的阻塞是應用層調用select()接口,poll()接口就是添加讀、寫等待隊列,返回POLLIN或POLLOUT的狀態。poll_wait()函數所做的工作是把當前進程添加到
wait 參數指定的等待列表(poll_table)中。通常在接收中斷中根據某個接收條件調用wait_up_interruptible(讀等待隊列),而在發送中斷中根據某個發送條件調用wait_up_interruptible(寫等待隊列)。那麼有人就會問:如果一個線程只操作寫,另一個線程只操作讀,而由於poll()中添加了讀與寫的等待隊列,兩個條件中的一個都會喚醒select()去遍歷監聽的讀、寫文件set。如果接收產生了條件喚醒了select(),那是不是也會喚醒發送的那個線程呢?這就需要靠應用層在調用select()接口時的配置了。詳細的調用如下圖所示:
關於驅動中的poll_wait,它的作用就是把當前進程添加到wait參數指定的等待列表(poll_table)中。需要注意的是這個函數是不會引起阻塞。那如果poll_wait不阻塞,當應用層調用select()系統調用時,真正實現阻塞功能是哪裏實現的呢?其實真正的阻塞是在應用層上的select接口函數中。
poll_wait()是用在select系統調用中的.
一般你的代碼會有一個struct file_operations結構,
其中fop->poll函數指針指向一個你自己的函數,
在這個函數裏應該調用poll_wait()
當用戶調用select系統調用時,select系統調用會
先調用
poll_initwait(&table);
然後調用你的
fop->poll();
從而將current加到某個等待隊列(這裏調用poll_wait()),
並檢查是否有效
如果無效就調用
schedule_timeout();
去睡眠.
事件發生後,schedule_timeout()回來,調用
fop->poll();
檢查到可以運行,就調用
poll_freewait(&table);
從而完成select系統調用.
重要的是fop->poll()裏面要檢查是否就緒,
如果是,要返回相應標誌