阻塞操作是指在執行裝置操作時若不能獲得資源則掛起進程,直到滿足可操作的條件後在進行操作。非阻塞操作的進程在不能進行裝置操作時並不掛起,它或者被放棄,或者不停的查詢,直到可以進行操作為止
喚醒進程的地方最大可能發生在中斷裡面,因為硬體資源獲得的同時往往伴隨著一個中斷
在使用者程式中,select()和poll()也是與裝置阻塞與非阻塞訪問息息相關的,使用非阻塞I/O的應用程式通常會使用select和poll系統調用查詢是否可對裝置進行無阻塞的訪問。select和poll系統調用最終會引發裝置驅動中的poll函數被執行
Poll函數原型:
Unsigned int(*poll)(struct file *filp, struct poll_table *wait);
第一個參數為file結構體指標,第二個參數為輪詢表指標。這個函數應該進行以下兩項工作
1、對可能引起裝置檔案狀態變化的等待隊列調用poll_wait()函數,將對應等待隊列添加到 poll_table
2、返回表示是否能對裝置進行無阻塞、寫訪問的掩碼
Poll_wait()函數不會引起阻塞。它所做的工作就是把當前進程添加到wait參數指定的等待列表(poll_table)中
驅動程式poll函數應該返回裝置資源的可擷取狀態
FD_ZERO(fd_set *fdset);將指定的檔案描述符集清空,在對檔案描述符集合進行設定前,必須對其進行初始化,如果不清空,由於在系統分配記憶體空間後,通常並不作清空處理,所以結果是不可知的。
FD_SET(fd_set *fdset);用於在檔案描述符集合中增加一個新的檔案描述符。
FD_CLR(fd_set *fdset);用於在檔案描述符集合中刪除一個檔案描述符。
FD_ISSET(int fd,fd_set *fdset);判斷檔案描述符是否被置位
Linux下select調用的過程:
1、使用者層應用程式調用select(),底層調用poll())
2、核心層調用sys_select() ------> do_select()
最終調用檔案描述符fd對應的struct file類型變數的struct file_operations *f_op的poll函數。
poll指向的函數返回當前可否讀寫的資訊。
1)如果當前可讀寫,返回讀寫資訊。
2)如果當前不可讀寫,則阻塞進程,並等待驅動程式喚醒,重新調用poll函數,或逾時返回。
3、驅動需要實現poll函數。
當驅動發現有資料可以讀寫時,通知核心層,核心層重新調用poll指向的函數查詢資訊。
poll_wait(filp,&wait_q,wait) // 此處將當前進程加入到等待隊列中,但並不阻塞
在中斷中使用wake_up_interruptible(&wait_q)喚醒等待隊列
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/dingyuanpu/archive/2010/05/09/5572350.aspx