通常來說,從普通檔案讀資料,無論你是採用 fscanf,fgets 也好,read 也好,一定會在有限的時間內返回。但是如果你從裝置,比如終端(標準輸入裝置)讀資料,只要沒有遇到換行符(『\n』),read 一定會「堵」在那而不返回。還有比如從網路讀資料,如果網路一直沒有資料到來,read 函式也會一直堵在那而不返回。
read 的這種行為,稱之為 block,一旦發生 block,本程序將會被作業系統投入睡眠,直到等待的事件發生了(比如有資料到來),程序才會被喚醒。
系統呼叫 write 同樣有可能被阻塞,比如向網路寫入資料,如果對方一直不接收,本端的緩衝區一旦被寫滿,就會被阻塞。
比如下面的程式
int main()
return 0;
}
gcc –o main.out main.c
./main.out
如果不向終端輸入資料,程式將永遠阻塞在read系統呼叫處。要規避這個問題,我們就需要用到非阻塞的io。
對於乙個給定的描述符有兩種方法對其指定非阻塞i/o:
1) 如果呼叫open獲得描述符,則可指定o_nonblock標誌
2) 對於已開啟的乙個描述符,則可呼叫fcntl,由該函式開啟o_nonblock檔案狀態標誌。
程式如下:
set_f1是設定讀取的方式為非阻塞,clr_f1則是清除非阻塞的方式
#include
#include
#include
#include
#include
#include
#include
void set_f1(int fd,int flags)
void clr_f1(int fd,int flags)
char buf[50000];
int main()
}clr_f1(stdout_fileno,o_nonblock);
return 0;
}若標準輸出是普通檔案,則可以期望write只執行一次
root@maple-virtualbox:/home/maple/codeblock_prj/func_test#
./main.out < /etc/services > temp.file
read 19605 bytes
nwrite=19605,errno=0
root@maple-virtualbox:/home/maple/codeblock_prj/func_test# ls -al temp.file
-rw-r--r-- 1 root root 19605 8月 12 15:33
temp.file
但是,如果標準輸出是終端。則有時會返回錯誤。
root@maple-virtualbox:/home/maple/codeblock_prj/func_test#
cat stderr.out
read 19605 bytes
nwrite=14907,errno=0
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=-1,errno=11
nwrite=4698,errno=0
程式發出了多個write呼叫,但是只有部分真正輸出了資料。其他的都只返回了錯誤。這種形式的迴圈成為輪詢。在多使用者系統上會浪費cpu時間。
阻塞I O,非阻塞I O
拿 socket舉例。當read資料時,如果這時沒有資料可讀,阻塞i o會一直等待有資料讀,資料從kernel copy 到socket的buffer後返回 非阻塞i o會立即返回,但如果有資料可讀,非阻塞i o也是等資料從kernel copy 到socket的buffer後返回。以上是阻塞與非阻...
非阻塞IO和阻塞IO
非阻塞io和阻塞io 在網路程式設計中對於乙個網路控制代碼會遇到阻塞io 和非阻塞io 的概念,這裡對於這兩種socket 先做一下說明 基本概念 阻塞io socket 的阻塞模式意味著必須要做完io 操作 包括錯誤 才會返回。非阻塞io 非阻塞模式下無論操作是否完成都會立刻返回,需要通過其他方式...
非阻塞IO和阻塞IO
非阻塞io 和阻塞io 在網路程式設計中對於乙個網路控制代碼會遇到阻塞io 和非阻塞io 的概念,這裡對於這兩種socket 先做一下說明 基本概念 阻塞io socket 的阻塞模式意味著必須要做完io 操作 包括錯誤 才會 返回。非阻塞io 非阻塞模式下無論操作是否完成都會立刻返回,需要通過其他...