我正在尝试构建一个可再发行的二进制文件,以安装一个只有glibc2.3的旧NAS。因此,pipe2()在该机器上不可用,但是我试图构建的代码有以下一行:
if (pipe2(info_pipe, O_CLOEXEC | O_NONBLOCK) < 0)
goto info_pipe_err;我的理解是,pipe2()存在的原因是通过在打开时使用O_CLOEXEC | O_NONBLOCK来避免竞争条件,而不是分两步进行。但是在我看的情况下没有线程,所以我想我可以代替:
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;
}但它似乎是不可互换的,因为代码不起作用。为什么这不是等价物?
发布于 2017-02-01 09:43:17
(回答我自己的问题是因为我搞清楚了,只是在这里为后人发帖。)
如果要在较新的编译器上为旧系统构建二进制文件,则运行时可能不知道O_CLOEXEC的值,因为pipe2()引入了该标志。如果它知道什么,它就知道FD_CLOEXEC。不使用F_SETFL设置,而是使用F_SETFD,这是一个单独的fcntl()调用。
以下替代办法应能奏效:
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()提供的线程安全方面,可以同时完成所有这些工作。
https://stackoverflow.com/questions/41976446
复制相似问题