POSIX标准允许在main()
之前调用fork()
吗?比如在C++的静态实例中或__attribute__((constructor))
的C函数中?
POSIX标准允许在main()
之前调用fork()
吗?比如在C++的静态实例中或__attribute__((constructor))
的C函数中?
fork
命令的文档中没有说明它是被禁止的,我也想不到任何理由会这样。
实际上,对于POSIX来说,main
没有任何特殊之处。只是C语言选择以该名称的函数开始程序,而C ++则几乎类似地做了同样的事情。但就POSIX而言,一旦进程启动,进程就启动了。 它可以用任何一种旧的语言编写,fork
仍然必须工作。
在C中(而不是C++!),你无法编写在main
之前执行的代码(因为在该上下文中,static
变量的初始化器必须是常量),因此对于C来说,这有点无关紧要。 但是,暂时离开C抽象,仍然没有POSIX阻止编译器供应商在C运行时中包含在进入 main
之前执行 fork
的代码。请记住,"真正"的入口点实际上不是 main
; "真正"的入口点执行一些库初始化等操作,然后调用main
来开始程序的部分。
main()
之前调用fork()
吗?这取决于你的意思。对于C程序,POSIX通过纳入C标准规定C程序启动时,环境(操作系统)会调用main()
。由此产生的POSIX定义语义从那一点开始;根据定义,它们不包括先前对任何其他函数的调用。如果实际上发生了任何这样的调用,则它们在这个意义上不是“程序”的一部分,因此该程序不能在main()
之前调用fork()
。另一方面,POSIX并没有明确禁止在定义的C语义开始之前,运行C程序所在的进程执行fork()
或任何其他函数。在未被禁止的情况下,POSIX允许这样做。如果你的问题是关于GCC的__attribute__((constructor))
或类似设施是否违反了POSIX,那么答案是否定的,尽管它们的行为没有被POSIX定义。第三方面,POSIX并没有肯定地允许它,并且没有定义任何C源代码指定它应该发生的方式。如果你的问题是关于POSIX是否定义了一个特定的设施,__attribute__((constructor))
或类似设施利用该设施提供其广告行为,或者它是否要求符合规范的系统必须提供这样的设施操作机制,那么答案也是否定的。不提供这样的机制不会本质上导致系统不符合POSIX。对于C++程序,POSIX是以shell命令语言和ISO C为基础定义的。它不要求实现提供任何C++支持,但当然也不禁止它。因此,前一节的第二段和第三段适用于C++程序的所有方面。值得一提的是,与C一样,C++指定程序从main()
开始。这在C++中具有类似的含义,但与C不同,C++实现可以提供机制,通过该机制可以使用户提供的代码在执行main()
的第一条语句之前运行。具有静态持续时间的变量的构造函数可能在执行main()
的第一条语句之前运行,但是否这样做是实现定义的(C++11,3.6.2/4)。在这个意义上,因此,在执行main()
的第一条语句之前调用fork()
是否包括在C++程序语义中是实现定义的。main()
之前进行 - 虽然这可能不重要,但至少有几种方法可以区分它们。main()
,它们也无法直接访问C库来显式地fork()
。在libc完全加载和初始化后,您可以使用fork。
一个简单的测试程序可以证明这是真的:
#include <stdio.h>
void before(void) __attribute__ (( constructor ));
void after(void) __attribute__ (( destructor ));
int main(void)
{
puts("main");
return 0;
}
void before(void)
{
puts("before");
}
void after(void)
{
puts("after");
}
$ LD_DEBUG=files ./a.out
26032:
26032: file=libc.so.6 [0]; needed by ./a.out [0]
26032: file=libc.so.6 [0]; generating link map
26032: dynamic: 0x00007f58c7703ba0 base: 0x00007f58c7341000 size: 0x00000000003c8a00
26032: entry: 0x00007f58c7361950 phdr: 0x00007f58c7341040 phnum: 10
26032:
26032:
26032: calling init: /lib/x86_64-linux-gnu/libc.so.6
26032:
26032:
26032: initialize program: ./a.out
26032:
before
26032:
26032: transferring control: ./a.out
26032:
main
26032:
26032: calling fini: ./a.out [0]
26032:
after
库已加载,初始化完成,因此可以安全地使用标记构造函数的fork。
__attribute__
并非标准C语言或POSIX规范,而C++是一种不同的语言。 - too honest for this sitemain()
之前调用fork()
函数? - EOF