天天看點

阻塞IO與非阻塞IO阻塞IO非阻塞IO測試代碼參考連結

阻塞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