POSIX标准是否允许在fork()
之前调用main()
- 例如,在C ++ static
实例中,或在__attribute__((constructor))
C函数中?
答案 0 :(得分:7)
fork
联机帮助页中没有任何迹象表明它已被禁止,我也无法想出它的原因。
事实上,就POSIX而言,main
并没有什么特别之处;只是C选择在具有该名称的函数中开始其程序,而C ++几乎几乎一样。但就POSIX而言,一旦您的流程启动,您的流程就会启动。它本来可以用任何旧语言编写,fork
仍然需要工作。
在C( not C ++!)中,你不可能编写在main
之前执行的代码(因为static
变量的初始化者在那种情况下必须保持不变),所以对于C来说,这有点没什么意义。但是,暂时退出C抽象,POSIX中仍然没有任何东西阻止编译器供应商在进入fork
之前在执行main
的C运行时中包含代码。回想一下" true"入口点实际上不是main
; " true"在调用main
开始你的程序部分之前,入口点会做一些库初始化和诸如此类的事情。
答案 1 :(得分:5)
POSIX标准是否允许在
fork()
[...]之前调用main()
?
这取决于你的意思。
POSIX通过结合C标准,指定在环境(操作系统)调用main()
时发生C程序启动。 POS程序定义的C程序语义从那时开始;根据定义,它们不包括先前对任何其他功能的调用。如果发生任何此类呼叫,那么它们不属于"程序"从这个意义上说, 程序 无法在fork()
之前调用main()
。
另一方面,POSIX没有明确禁止C程序在定义的C语义开始之前运行以执行fork()
或任何其他函数的过程。从某种意义上说,允许不被禁止的东西,POSIX确实允许它。如果您的问题是关于GCC的__attribute__((constructor))
或类似设施是否违反POSIX,那么他们不会,但他们的行为不是由POSIX定义的。
第三方面,POSIX没有肯定地允许它,并且没有为C源代码定义任何方式来指定它应该发生。如果您的问题是关于POSIX是否定义__attribute__((constructor))
或类似设施用于提供其广告行为的特定设施,或者是否要求符合要求的系统必须提供此类设施可以运行的机制,那么不,它没有& #39;吨。不提供这样的机制本身不会导致系统无法符合POSIX。
POSIX是根据shell命令语言和ISO C定义的。它根本不要求实现提供任何C ++支持,但当然它也不禁止它。因此,上一节的第二和第三段适用于C ++程序的所有方面。
然而,对于它的价值,如C,C ++指定程序从main()
开始。这在C ++中与在C中具有相似的含义,但与C不同,C ++实现可能提供了一些机制,通过这些机制,用户提供的代码可以在main()
的第一个语句之前运行。具体来说,具有静态持续时间的变量的构造函数可以在执行main()
的第一个语句之前运行,但它是否这样做是实现定义的(C ++ 11,3.6.2) / 4)。因此,在这个意义上,它是实现定义的C ++程序语义是否可以在fork()
的第一个语句之前包含对main()
的调用。
另请注意,C ++标准是经过精心设计的,以避免在main()
之前进行此类初始化 - 这可能并不重要,但有至少有两种方法可以区分它们。
main()
,并且他们无法直接访问C库,明确fork()
。
答案 2 :(得分:2)
从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
已加载库,已完成初始化,因此使用带有construtor标记函数的fork必须是安全的。