简体   繁体   中英

Calling fork before main

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

There is no indication in the fork manpage that it's prohibited, nor can I think of a reason for it to be.

Indeed, there's nothing special about main as far as POSIX is concerned; it's just that C chooses to begin its programs in a function with that name, and C++ sort of almost nearly does the same. But as far as POSIX is concerned, once your process is up, your process is up. It could have been written in any old language, and fork would still have to work.

In C ( not C++!) it is impossible for you to write code that executes before main (because initialisers for static variables must be constant in that context), so for C it's a bit of a moot point. However, stepping outside of the C abstraction for a moment, there's still nothing in POSIX stopping your compiler vendor from including code in the C runtime that performs a fork before entering main . Recall that the "true" entrypoint is not actually main ; the "true" entrypoint does some library initialisations and whatnot before invoking main to begin your part of the program.

Does the POSIX standard allow calling fork() before main() [...] ?

It depends on what you mean.

C programs

POSIX, through its incorporation of the C standard, specifies that C program startup occurs when the environment (operating system) calls main() . The POSIX-defined semantics of the C program start at that point; by definition, they do not include prior calls to any other function. If any such calls in fact occur then they are not part of "the program" in this sense, so the program cannot call fork() before main() .

On the other hand, POSIX does not explicitly forbid the process in which a C program runs to execute fork() or any other function prior to the commencement of the defined C semantics. In the sense that what is not forbidden is allowed, POSIX does allow it. If your question is about whether GCC's __attribute__((constructor)) or similar facilities violate POSIX then no, they don't, though their behavior is not defined by POSIX.

On the third hand, POSIX does not affirmatively allow it, and does not define any way for C source code to specify that it should happen. If your question is about whether POSIX defines a specific facility that __attribute__((constructor)) or similar facilities leverage to provide their advertised behavior, or whether it requires that conforming systems must provide a mechanism by which such facilities can operate, then no, it doesn't. Not providing such a mechanism would not inherently cause a system to fail to conform to POSIX.

C++ programs

POSIX is defined in terms of the shell command language and ISO C. It does not require implementations to provide any C++ support at all, but of course it does not forbid it, either. Thus, the second and third paragraphs of the previous section apply to all aspects of C++ programs.

For what it's worth, however, like C, C++ specifies that programs start in main() . This has similar meaning in C++ as in C, but unlike C, C++ implementations may provide mechanisms by which user-provided code can be made to run before the first statement of main() . Specifically, the constructor for a variable with static duration may run before the first statement of main() is executed, but whether it does so is implementation-defined (C++11, 3.6.2/4). In this sense, therefore, it is implementation-defined whether the C++ program semantics can include a call to fork() before the first statement of main() .

Note also that the C++ standard is carefully worded to avoid speaking to whether such initializations can be before main() is entered -- that's probably immaterial, but there are at least a couple of ways in which it would be possible to tell the difference.

Other programs

POSIX has even less to say about other kinds of programs than it has to say about C++ programs, except for shell scripts. Of course, shell scripts generally don't have a main() at all, and they have no direct access to the C library by which to explicitly fork() .

You can use fork from the moment the libc is fully loaded and initialized.

A simple test program can show this is true :

 #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");
 }

The output is :

 $ 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

Library loaded, initializations done, so it must be safe to use fork with a construtor tagged function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM