![处理 Pipe() 的不同原型](https://linux22.com/image/206734/%E5%A4%84%E7%90%86%20Pipe()%20%E7%9A%84%E4%B8%8D%E5%90%8C%E5%8E%9F%E5%9E%8B.png)
根据这个联机帮助页,pipe()
根据架构可以有不同的原型。如果我想尽可能跨平台,我现在是否必须编写在给定任一原型时进行编译的代码?这是合理的(甚至可能的吗?)?或者,我可以使用预处理器指令检查架构吗?
关于跨平台的话题,POSIX 只提到了第一个原型,但 Linux 联机帮助页并未将第二个突出显示为不符合 POSIX 标准。这是一个错误吗?
1 我一直在尝试使用 C++20 功能来实现某些功能,但尚未成功。
答案1
pipe
您找到的手册页有两个不同的目的:
- 它记录了 Linux 内核使用的系统调用接口。
- 它记录了 Linux 上 GNU C 库提供的系统调用包装器。
前者可能因一种架构而异,而另一种则不同。这就是这里正在发生的事情。GNU C 库提供的包装器然而实现POSIX pipe
API:
#include <unistd.h>
int pipe(int fildes[2]);
使用 编译或链接程序时不会有任何歧义pipe
,即使在诸如 Alpha 之类的系统调用 API 不同的体系结构上也是如此:系统调用 API没有像这样出现在系统的头文件或系统库中(尽管手册页似乎确实表明了这一点)。在 Alpha Linux 系统上,GNU C 库声明pipe
如下,与其他 Linux 体系结构相同:
/* Create a one-way communication channel (pipe).
If successful, two file descriptors are stored in PIPEDES;
bytes written on PIPEDES[1] can be read from PIPEDES[0].
Returns 0 if successful, -1 if not. */
extern int pipe (int __pipedes[2]) __THROW __wur;
因此,在 Alpha 上,如果您编写一个假设该struct fd_pair pipe(void);
变体的程序,它将无法构建。
要访问系统调用本身,您必须使用syscall
GNU C库提供的函数或者自己编写系统调用代码。那是当您必须提供特定于架构的代码时;但很少有人需要真正关心这个。
不幸的是,在 Linux 系统上,手册页最终可能会以这种方式变得混乱,因为 C 库本身不提供任何内容;因此包装系统调用的函数调用最终由系统调用手册页记录。如果您不关心系统调用本身(实际上大多数开发人员也不关心),那么您最好阅读GNU C 库的文档如果您使用该库在 C 中进行编程,或者您正在使用的运行时库的文档(如果不是)。
答案2
如果我想尽可能跨平台,我现在是否必须编写在给定任一原型时进行编译的代码?
不,这里没有必要。
您正在查看第 2 部分联机帮助页条目,了解直接系统调用。这就是您的语言运行时实现者将吸收的文档,直到它充满他们的存在并告知他们的闲散想法。
您需要第 3 节文档,即 C 系列运行时。man 3 pipe
对我来说,它可以作为谷歌搜索,也可以作为命令。如果您使用任何 C 系列语言,这就是您要链接的原型,您的工具链究竟如何安排让可移植第 3 节 api 调用您找到文档的系统特定第 2 节 api 是......我怀疑您需要获取要链接的任何运行时的源代码,libc++ 或 libstdc++ 或 glibc,不知道也不关心,对于可移植代码,第 3 节 API 应该只是工作™。