ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Linux-STDIN_FILENO和STDOUT_FILENO的非阻塞I / O行为很奇怪

2019-12-01 16:50:39  阅读:393  来源: 互联网

标签:nonblocking linux


我有以下代码:

void
set_fl(int fd, int flags) /* flags are file status flags to turn on */
{
    int val;

    if ((val = fcntl(fd, F_GETFL, 0)) < 0)
        err_sys("fcntl F_GETFL error");

    val |= flags;       /* turn on flags */

    if (fcntl(fd, F_SETFL, val) < 0)
        err_sys("fcntl F_SETFL error");
}

int
main(void)
{
    char buf[BUFSIZ];
    set_fl(STDOUT_FILENO, O_NONBLOCK);  //set STDOUT_FILENO to nonblock
    if(read(STDIN_FILENO, buf, BUFSIZ)==-1) { //read from STDIN_FILENO
        printf("something went wrong with read()! %s\n", strerror(errno));
    }
}

如您所见,我将STDOUT_FILENO设置为非阻塞模式,但似乎对STDIN_FILENO的读取操作立即完成.为什么?

$./testprog
something went wrong with read()! Resource temporarily unavailable

谢谢

解决方法:

完全正确:读取后立即打印errno和进行错误调用,结果是“资源繁忙”,错误号为11或EAGAIN / EWOULDBLOCK,如以下代码所示:

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>

int main (void) {
    char buf;

    fcntl (STDOUT_FILENO, F_SETFL, fcntl (STDOUT_FILENO, F_GETFL, 0) | O_NONBLOCK);
    fprintf (stderr, "%5d: ", errno); perror("");
    read (STDIN_FILENO, &buf, 1);
    fprintf (stderr, "%5d: ", errno); perror("");
}

产生:

    0: Success
   11: Resource temporarily unavailable

原因是文件描述符具有两种不同类型的标志(请参见详细说明复制文件描述符的部分中的here):

You can duplicate a file descriptor, or allocate another file descriptor that refers to the same open file as the original. Duplicate descriptors share one file position and one set of file status flags (see File Status Flags), but each has its own set of file descriptor flags (see Descriptor Flags).

第一个是file descriptor flags,每个文件描述符确实是唯一的.根据文档,FD_CLOEXEC(在exec上关闭)是当前在这一阵营中唯一的一个.

所有其他标志均为file status flags,并在已重复的文件描述符中共享.这些包括I/O operating modes,例如O_NONBLOCK.

因此,这里发生的是,标准输出文件描述符是从标准输入文件中复制的(顺序无关紧要,只是一个文件与另一个文件被复制的事实),因此在一个文件上设置非阻塞模式会影响所有副本(尽管我尚未确认,但它可能还包括标准错误文件描述符).

在复制的文件描述符上使用阻塞模式,或者在子进程中可能会继承的文件描述符,通常不是一个好主意-这些子进程并不总是善待标准文件的行为(从他们的角度来看).

如果要对单个文件描述符进行更细粒度的控制,请在尝试读取之前考虑使用select检查描述符.

标签:nonblocking,linux
来源: https://codeday.me/bug/20191201/2082162.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有