UNIX(编程-高级IO):01---非阻塞IO与轮询

一、阻塞IO

将系统调用分成两类:低速系统调用和其他

  • 低速系统调用是可能会使进程永远阻塞的一类系统调用,包括下面:

二、非阻塞IO

  • 概念:非阻塞I/O使我们可以调用不会永远阻塞的I/O操作,例如open,read和write。如果这种操作不能完成,则立即出错返回,表示该操作如继续执行将继续阻塞下去

对于给定的一个描述符,有两种方法对其指定非阻塞I/O:

  • 如果是调用open以获得该描述符,则可指定O_NONBLOCK标志
  • 对于已经打开的一个描述符,则可调用fcntl打开O_NONBLOCK文件状态标志

注意事项

三、非阻塞IO案例

  • 是一个非阻塞I/O的实例,它从标准输入读500000字节,并试图将它们写到标准输出上。该程序先将标准输出设置为非阻塞的,然后用for循环进行输出,每次write的结果都在标准出错上打印
  • 函数clr_fl清除文件描述符标志,它清除1个或多个标志位 
#include<errno.h>
#include<fcntl.h>
#include<stdlib.h>
#include<stdio.h>

char buf[500000];
void clr_fl(int fd, int flags);
void set_fl(int fd,int flags);

int main(void)
{
    int ntowrite, nwrite;
    char *ptr;

    ntowrite = read(0, buf, sizeof(buf));//从标准输入读取数据
    fprintf(stderr, "read %d bytes\n", ntowrite);

    set_fl(1, O_NONBLOCK); //设置标准输出非阻塞

    ptr = buf;
    while (ntowrite > 0) {
        errno = 0;
        nwrite = write(1, ptr, ntowrite);//将数据输出到标准输出上
        fprintf(stderr, "nwrite = %d, errno = %d\n", nwrite, errno);

        if (nwrite > 0) {
            ptr += nwrite;
            ntowrite -= nwrite;
        }
    }

    clr_fl(2, O_NONBLOCK); //设置标准输出阻塞
    exit(0);
}
void clr_fl(int fd, int flags)
{
    int val;
    if ((val = fcntl(fd, F_GETFL, 0)) < 0)//先得到
        perror("fcntl F_GETFL error");
    val &= ~ flags; /* turn off flags */
    if (fcntl(fd, F_SETFL, val) < 0)//再设置
        perror("fcntl F_SETFL error");
}
void set_fl(int fd, int flags)
{
    int val;
    if ((val = fcntl(fd, F_GETFL, 0)) < 0)//先得到
        perror("fcntl F_GETFL error");
    val |= flags; /* turn on flags */
    if (fcntl(fd, F_SETFL, val) < 0)//再设置
        perror("fcntl F_SETFL error");
}

运行结果:

  • ①如果标准输出是普通文件,则可期望write只执行了一次

  • ②如果标准输出是终端,则期望write有时小于50000的一个数字,有时返回错误

四、轮询

猜你喜欢

转载自blog.csdn.net/qq_41453285/article/details/89330903