阻塞、非阻塞IO

阻塞与非阻塞是对于文件而言的,而不是指read、write等的属性。

阻塞IO

应用程序调用IO函数,导致应用程序阻塞,等待数据准备好。如果数据没有准备好,一直等待数据准备好了,从内核拷贝到用户空间,IO函数返回成功指示。

这里写图片描述

读常规文件是不会阻塞的,不管读多少字节,read一定会在有限的时间内返回。一般网络、终端设备IO都是阻塞I/O。

如果从终端输入的数据没有换行符,调用read读终端设备就会阻塞,如果网络上没有接收到数据包,调用read从网络读就会阻塞,至于会阻塞多长时间也是不确定的,如果一直没有数据到达就一直阻塞在那里。

示例代码:

#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
    char buf[1024] = {0};
    printf("读数据前:\n");
    read(0, buf, sizeof(buf));  //默认是阻塞的,从标准输入读取内容
    printf("读取数据后:buf = %s\n", buf);

    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

运行结果: 
这里写图片描述

非阻塞IO

我们把一个文件设置为非阻塞就是告诉内核,当所请求的I/O操作无法完成时,不要将进程睡眠,而是返回一个错误(EAGAIN)。

这样我们的I/O操作函数将不断的测试数据是否已经准备好,如果没有准备好,继续测试,直到数据准备好为止。在这个不断测试的过程中,会大量的占用CPU的时间,所有一般Web服务器都不使用这种I/O模型。 
这里写图片描述

示例代码:

#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
    int fd;
    //以非阻塞方式打开当前终端
    fd = open("/dev/tty", O_RDONLY|O_NONBLOCK); 
    if(fd < 0)
    {
        perror("open\n");
        return -1;
    }

    char buf[1024];
    while(1)
    {   
        int n = read(fd, buf, sizeof(buf));
        printf("n = %d, errno = %d, EAGAIN = %d\n", n, errno, EAGAIN);
        sleep(1); //延时

        if(n <= 0)
        {
            //如果为非阻塞,但是没有数据可读,此时全局变量 errno 被设置为 EAGAIN
            if(errno == EAGAIN)
            {
                printf("没有数据可读\n");
            }
            else
            {
                perror("read");
                break;
            }
        }
        else
        {//有数据
            printf("buf = %s\n", buf);
            break;
        }
    }

    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

运行结果: 

这里写图片描述

转载请注明出处: https://blog.csdn.net/tennysonsky/article/details/78534432

猜你喜欢

转载自blog.csdn.net/broadCE/article/details/80065226