1. 程式人生 > >Linux 裝置驅動中的阻塞與非阻塞I/O

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

   }

  }

}