首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Pipe2(.)vs pipe() +fcntl(.),为什么不同?

Pipe2(.)vs pipe() +fcntl(.),为什么不同?
EN

Stack Overflow用户
提问于 2017-02-01 09:42:50
回答 1查看 1.9K关注 0票数 1

我正在尝试构建一个可再发行的二进制文件,以安装一个只有glibc2.3的旧NAS。因此,pipe2()在该机器上不可用,但是我试图构建的代码有以下一行:

代码语言:javascript
复制
if (pipe2(info_pipe, O_CLOEXEC | O_NONBLOCK) < 0)
    goto info_pipe_err;

我的理解是,pipe2()存在的原因是通过在打开时使用O_CLOEXEC | O_NONBLOCK来避免竞争条件,而不是分两步进行。但是在我看的情况下没有线程,所以我想我可以代替:

代码语言:javascript
复制
if (pipe(info_pipe) < 0)
    goto info_pipe_err;

int direction; // 0=READ, 1=WRITE
for (direction = 0; direction < 2; ++direction) {
    int oldflags;
    oldflags = fcntl(info_pipe[direction], F_GETFL);

    if (oldflags < 0)
        goto info_pipe_err;

    if (fcntl(info_pipe[direction], 
        F_SETFL, oldflags | O_NONBLOCK | O_CLOEXEC) < 0)
        goto info_pipe_err;
}

但它似乎是不可互换的,因为代码不起作用。为什么这不是等价物?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-02-01 09:43:17

(回答我自己的问题是因为我搞清楚了,只是在这里为后人发帖。)

如果要在较新的编译器上为旧系统构建二进制文件,则运行时可能不知道O_CLOEXEC的值,因为pipe2()引入了该标志。如果它知道什么,它就知道FD_CLOEXEC。不使用F_SETFL设置,而是使用F_SETFD,这是一个单独的fcntl()调用。

以下替代办法应能奏效:

代码语言:javascript
复制
if (pipe(info_pipe) < 0)
    goto info_pipe_err;

int direction; // 0=READ, 1=WRITE
for (direction = 0; direction < 2; ++direction) {
    int oldflags;
    oldflags = fcntl(info_pipe[direction], F_GETFL);

    if (oldflags < 0)
        goto info_pipe_err;

    if (fcntl(info_pipe[direction],
        F_SETFL, oldflags | O_NONBLOCK) < 0)
        goto info_pipe_err;

    oldflags = fcntl(info_pipe[direction], F_GETFD);
    if (oldflags < 0)
        goto info_pipe_err;

    if (fcntl(info_pipe[direction],
        F_SETFD, oldflags | FD_CLOEXEC) < 0)
        goto info_pipe_err;
}

如前所述,这不具有pipe2()提供的线程安全方面,可以同时完成所有这些工作。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41976446

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档