http://www.CUOXin.com/nufangrensheng/p/3515035.html中曾將系統調用分成“低速”系統調用和其他系統調用兩類。低速系統調用是可能會使進程永遠阻塞的一類系統調用,它們包括下列調用:
雖然讀、寫磁盤文件會使調用者在短暫時間內阻塞,但并不能將與磁盤I/O有關的系統調用視為“低速”。
非阻塞I/O使我們可以調用open、read和write這樣的I/O操作,并使這些操作不會永遠阻塞。如果這種操作不能完成,則調用立即出錯返回,表示該操作如繼續執行將阻塞。
對于一個給定的描述符有兩種方法對其指定非阻塞I/O:
(1)如果調用open獲得描述符,則可指定O_NONBLOCK標志(http://www.CUOXin.com/nufangrensheng/p/3497789.html)。
(2)對于已經打開的一個描述符,則可調用fcntl,由該函數打開O_NONBLOCK文件狀態標志(http://www.CUOXin.com/nufangrensheng/p/3500350.html,其中,程序清單3-5中的函數可用來為一個描述符打開任一文件狀態標志)。
系統V的早期版本使用標志O_NDELAY指定非阻塞方式。在這些版本中,如果無數據可讀,則read返回值0。而UNIX系統又常將read返回值0解釋為文件結束,兩者有所混淆。因此POSIX.1提供了一個名字和語義都與O_NDELAY不同的非阻塞標志。確實,在系統V的早期版本中,當從read得到返回值0時,我們并不知道該調用是否阻塞了或已到文件結尾處。POSIX.1要求,對于一個非阻塞的描述符如果無數據可讀,則read返回-1,并且errno被設置為EAGAIN。系統V派生的某些平臺支持較老的O_NDELAY和POSIX.1的O_NONBLOCK兩者。O_NDELAY只是為了向后兼容,不應在新應用程序中使用。
4.3BSD為fcntl提供了FNDELAY標志,其語義也稍有區別。它不只影響描述符的文件狀態標志,還將終端設備或套接字的標志更改成非阻塞的,因此不僅影響共享同一文件表項的用戶,而且對終端或套接字的所有用戶其作用。另外,如果對一個非阻塞描述符的操作不能無阻塞地完成,那么4.3BSD返回EWOULDBLOCK?,F今,基于BSD的系統提供POSIX.1的O_NONBLOCK標志,并且將EWOULDBLOCK定義為與POSIX.1的EAGAIN相同。這些系統提供與其他依從POSIX系統相一致的非阻塞語義。文件狀態標志的更改影響同一文件表項的所有用戶,但與通過其他文件表項對同一設備的訪問無關(參加圖3-1http://www.CUOXin.com/nufangrensheng/p/3498509.html和圖3-3http://www.CUOXin.com/nufangrensheng/p/3498736.html)。
實例
程序清單14-1是一個非阻塞I/O的實例,它從標準輸入讀500 000字節,并試圖將它們寫到標準輸出上。該程序先將標準輸出設置為非阻塞的,然后用for循環進行輸出,每次write調用的結果都在標準出錯上打印。函數clr-fl類似于程序清單3-5(http://www.CUOXin.com/nufangrensheng/p/3500350.html)中的set_fl,但與set_fl的功能相反,它清除1個或多個標志位。
程序清單14-1 長的非阻塞write
#include "apue.h"#include <errno.h>#include <fcntl.h>char buf[500000];extern void set_fl(int, int);extern void clr_fl(int, int);intmain(void){ int ntowrite, nwrite; char *ptr; ntowrite = read(STDIN_FILENO, buf, sizeof(buf)); fPRintf(stderr, "read %d bytes/n", ntowrite); set_fl(STDOUT_FILENO, O_NONBLOCK); /* set nonblocking */ ptr = buf; while(ntowrite > 0) /* 這種形式的循環稱為輪循,在多用戶系統上它浪費了CPU時間。*/ { errno = 0; nwrite = write(STDOUT_FILENO, ptr, ntowrite); fprintf(stderr, "nwrite = %d, errno = %d/n", nwrite, errno); if(nwrite > 0) { ptr += nwrite; ntowrite -= nwrite; } } clr_fl(STDOUT_FILENO, O_NONBLOCK); /* clear nonblocking */ exit(0);}
本篇博文內容摘自《UNIX環境高級編程》(第二版),僅作個人學習記錄所用。關于本書可參考:http://www.apuebook.com/。
新聞熱點
疑難解答