阻塞IO與非阻塞IO
阻塞IO
預設情況下,Linux系統上的所有檔案描述符都以阻塞模式開始。 這意味着I / O系統調用如讀取,寫入或連接配接可能會阻塞。
如果你在stdin上調用read,那麼你的程式将被阻塞,直到資料實際可用,例如當使用者實際上在他們的鍵盤上實體鍵入字元時。具體來說,核心會将程序置于“睡眠”狀态,直到資料在stdin上可用。
網絡傳輸中,如果你嘗試從TCP套接字讀取,則讀取調用将阻塞,直到連接配接的另一端實際發送資料。這種網絡設定在高并發環境下就是災難,因為隻要達到阻塞的上限,那麼剩下請求則沒法處理。
非阻塞IO
非阻塞IO在沒有資料處理的情況下直接傳回且errno = 11。errno 在errno.h的定義如下:
#define EAGAIN 11
設定非阻塞IO的方式
1使用fcntl在檔案描述符上設定O_NONBLOCK
int flags = fcntl(STDIN_FILENO,F_GETFL,0);
fcntl(STDIN_FILENO,F_SETFL,flags | O_NONBLOCK );
flags = fcntl(STDIN_FILENO,F_GETFL,0);
fcntl(STDIN_FILENO,F_SETFL,flags & (~O_NONBLOCK) );
2使用open函數,其中flags項包括O_NONBLOCK。
int fd =open("test",O_RDWR|O_CREAT|O_NONBLOCK);
測試代碼
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include <unistd.h>
char buf[500000];
int
main(void)
{
int ntowrite, nwrite;
char *ptr;
/*STDIN_FILENO 開啟非阻塞模式 */
int flags = fcntl(STDIN_FILENO,F_GETFL,0);
fcntl(STDIN_FILENO,F_SETFL,flags | O_NONBLOCK );
/*STDIN_FILENO 開啟非阻塞模式 */
/*從STDIN_FILENO讀取資料,如果是非阻塞模式,沒讀到資料則立刻傳回 */
ntowrite = read(STDIN_FILENO, buf, sizeof(buf));
fprintf(stderr, "read %d bytes\n", ntowrite);
/*open函數設定描述符,開啟非阻塞模式 */
int fd =open("test",O_RDWR|O_CREAT|O_NONBLOCK);
ptr = buf;
while (ntowrite > 0) {
errno = 0;
nwrite = write(fd, ptr, ntowrite);
fprintf(stderr, "nwrite = %d, errno = %d\n", nwrite, errno);
if (nwrite > 0) {
ptr += nwrite;
ntowrite -= nwrite;
}
}
/* STDIN_FILENO 關閉非阻塞模式*/
flags = fcntl(STDIN_FILENO,F_GETFL,0);
fcntl(STDIN_FILENO,F_SETFL,flags & (~O_NONBLOCK) );
close(fd);
exit(0);
}
參考連結
[1]. https://www.mkssoftware.com/docs/man5/stdio.5.asp
[2]. http://www.virtsync.com/c-error-codes-include-errno