Linux 裝置驅動中的阻塞與非阻塞I/O
何謂阻塞與非阻塞I/O?簡單來說就是對I/O操作的兩種不同的方式。
阻塞:當操作I/O裝置時,如果不能得到相應的資源,則該程序進入休眠狀態,被從排程器的佇列中移走,直到等待的條件滿足。
阻塞的讀取一個字元:
char buf;
fd = open("/dev/ttyS1",O_RDWR);
.....
res = read(fd,&buf,1); //當串列埠上有輸入時才返回,沒有輸入則程序掛起睡眠
if(res == 1)
{
printf("%c/n",buf);
}
非阻塞:當不能對I/O裝置進行操作時,它或者放棄,或者不停的查詢,直到可以進行操作為止。
非阻塞的讀一個字元:
char buf;
fd = open("/dev/ttyS1",O_RDWR|O_NONBLOCK);//O_NONBLOCK 非阻塞標識
.....
while(read(fd,&buf,1)!=1);//串列埠上沒有輸入則返回,所以迴圈讀取
printf("%c/n",buf);
阻塞操作常常用等待佇列來實現,而非阻塞操作用輪詢的方式來實現。
非阻塞I/O的操作在應用層通常會用到select()和poll()系統呼叫查詢是否可對裝置進行無阻塞訪問。select()和poll()系統呼叫最終會引發
裝置驅動中的poll()函式被呼叫。
應用層的select()原型為:int select(int numfds,fd_set *readfds,fd_set *writefds,fd_set *exceptionfds,
struct timeval *timeout); numfds 的值為需要檢查的號碼最高的檔案描述符加1,若select()在等待timeout時間後,若沒有檔案描述符準備好則返回。
應用程式為:
#inlcude---
---
main()
{
int fd,num;
char rd_ch[BUFFER_LEN];
fd_set rfds,wfds; //讀寫檔案描述符集
//以非阻塞方式開啟/dev/globalfifo裝置檔案
fd = open("/dev/globalfifo",O_RDWR|O_NONBLOCK);
if(fd != -1)
{
//FIFO 清零
if(ioctl(fd,FIFO_CLEAR,0) < 0)
{
printf("ioctl cmd failed /n");
}
while(1)
{
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_SET(fd,&rfds);
FD_SET(fd,&wfds);
select(fd+1,&rfds,&wfds,null,null);
if
}
}
}