天天看点

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