在主要之前调用fork

时间:2016-06-14 16:36:57

标签: c++ c fork posix language-lawyer

POSIX标准是否允许在fork()之前调用main() - 例如,在C ++ static实例中,或在__attribute__((constructor)) C函数中?

3 个答案:

答案 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()

这取决于你的意思。

C程序

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。

C ++程序

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() 之前进行此类初始化 - 这可能并不重要,但有至少有两种方法可以区分它们。

其他节目

除了shell脚本之外,对于其他类型的程序,POSIX对C ++程序的评价甚少。当然,shell脚本通常根本没有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必须是安全的。