【Linux编程】非阻塞I/O

系统调用分为低速系统调用和其它系统调用两类。低速系统调用可能会使进程永远阻塞。但与磁盘I/O相关的系统调用不是低速系统调用,因为磁盘I/O操作会在一个可期望的未来成功。非阻塞I/O可以使普通的open、read、write这种系统调用不能完成时出错返回。

成为非阻塞I/O的两种方法:
  • open时设置O_NONBLOCK标识。
  • fcntl设置已打开的描述符,追加O_NONBLOCK标识。
下面是一个测试例程:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
 
char buf[500000];
 
int main(void)
{
    int  nread, nwrite, val;
    char *ptr;
 
    nread = read(STDIN_FILENO, buf, sizeof(buf));
    fprintf(stderr, "read %d bytes\n", nread);
 
    // 设置标准输出为非阻塞模式
    val = fcntl(STDOUT_FILENO, F_GETFL, 0);
    val |= O_NONBLOCK;
    fcntl(STDOUT_FILENO, F_SETFL, val);
 
    ptr = buf;
    while (nread > 0)
    {
        errno = 0;
        nwrite = write(STDOUT_FILENO, ptr, nread);
        fprintf(stderr, "nwrite = %d, errno = %d\n", nwrite, errno);
        if (nwrite > 0)
        {
            ptr += nwrite;
            nread -= nwrite;
        }
    }
 
    // 设置标准输出为阻塞模式
    val = fcntl(STDOUT_FILENO, F_GETFL, 0);
    val &= ~O_NONBLOCK;
    fcntl(STDOUT_FILENO, F_SETFL, val);
 
    return 0;
}


首先将输入输出重定向到文件:

由于标准输出重定向到了文件,那么现在是以阻塞的方式调用write,一次就把所有数据写进去了。

再看看将数据写到标准输出:

屏幕上会正常输出CHANGES文件中的内容,看看stderr.out中的读写情况:
stderr.out文件中,绝大部分都是出错信息,错误号11表示EAGAIN。

参考:
《unix环境高级编程》 P355-P357.

你可能感兴趣的:(【Linux编程】非阻塞I/O)