加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

linux – 管道上的非阻塞读取

发布时间:2020-12-13 23:52:28 所属栏目:Linux 来源:网络整理
导读:可以在管道上进行非阻塞I / O吗? fcntl无法设置O_NONBLOCK. Linux编程接口的页面918包括一个表’从管道读取n个字节或FIFO(p)’的语义.此表列出了管道和FIFO的行为,其中一列标题为O_NONBLOCK已启用?这意味着您可以在管道上设置O_NONBLOCK标志.它是否正确?
可以在管道上进行非阻塞I / O吗? fcntl无法设置O_NONBLOCK. Linux编程接口的页面918包括一个表’从管道读取n个字节或FIFO(p)’的语义.此表列出了管道和FIFO的行为,其中一列标题为O_NONBLOCK已启用?这意味着您可以在管道上设置O_NONBLOCK标志.它是否正确?以下代码无法设置标志,但fcntl(2)不报告错误.

#include <fcntl.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

#define SLEEP 1

int
main(int argc,char *argv[]) {
    pid_t childPid;
    int pfd[2];
    int nread,flags;
    int c = 'a';    

    setbuf(stdout,NULL);

    if (pipe(pfd) == -1) {
        printf("error: pipe");
        exit(EXIT_FAILURE);
    }

    switch (childPid = fork()) {
    case -1:
        printf("error: fork");
        exit(EXIT_FAILURE);
    case 0:         /* child */
        if (close(pfd[0]) == -1) {
            printf("child: close pfd read");
            exit(EXIT_FAILURE);
        }
        sleep(SLEEP);
        _exit(EXIT_SUCCESS);
    default:
        break;
                /* parent falls through */
    }
    if (close(pfd[1]) == -1) {
        printf("parent: close pipe write");
        exit(EXIT_FAILURE);
    }

    flags = fcntl(pfd[0],F_GETFD);
    flags |= O_NONBLOCK;
    if (fcntl(pfd[0],F_SETFD,flags))
        perror("fcntl");

    /* verify flags set correctly */
    flags = fcntl(pfd[0],F_GETFD);
    if (!(flags & O_NONBLOCK))  {
        printf("failed to set O_NONBLOCKn");
        exit(EXIT_FAILURE);
    }

    wait(NULL);
    exit(EXIT_SUCCESS);
}

解决方法

管道和O_NONBLOCK没有什么特别之处.以下示例按预期工作.我没有检查每次调用的每个retval,以使示例更具可读性.真实世界的应用程序必须进行检查.

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

int main()
{
    int fds[2];
    pid_t pid;
    char buf[100];

    pipe(fds);

    pid = fork();

    if ( pid )
    {
        while (1 )
        {
            memcpy( buf,"abcdefghi",10);
            write( fds[1],buf,10);
            sleep(2);
        }
    }
    else
    {
        int retval = fcntl( fds[0],F_SETFL,fcntl(fds[0],F_GETFL) | O_NONBLOCK);
        printf("Ret from fcntl: %dn",retval);
        while (1)
        {
            ssize_t r=read( fds[0],10 );
            printf("read: %dn",r);

            if ( r > 0 )
            {
                printf("Buffer: %sn",buf);
            }
            else
            {
                printf("Read nothingn");
                perror("Error was");
                sleep(1);
            }
        }
    }
}

写完我的例子后,我检查你的代码,发现:

flags = fcntl(pfd[0],F_GETFD);
flags |= O_NONBLOCK;
if (fcntl(pfd[0],flags))

请将F_SETFD更改为F_SETFL以及get操作.您不会更改文件描述符标志,但文件描述符状态标志:-)

来自man 3 fcntl:

File descriptor flags
The following commands manipulate the flags associated with a file
descriptor. Currently,only one such flag is defined: FD_CLOEXEC,the
close-on-exec flag. If the FD_CLOEXEC bit is 0,the file descriptor
will remain open across an execve(2),otherwise it will be closed.

File status flags
Each open file description has certain associated status flags,ini

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读