vfork () chama SYS_vfork mas fork () chama SYS_clone?

0

Depois de executar ltrace -S em dois programas que foram compilados por gcc (versão 5.4.0), um que chama vfork() e um que chama fork() , descubro que vfork() chama SYS_vfork enquanto fork() chamadas SYS_clone . Não encontrei nenhuma informação sobre esse comportamento específico em lugar algum (algumas fontes dizem que fork() , vfork() e clone() são implementadas pela chamada sys_ correspondente, enquanto outras fontes dizem que todas as três chamadas são implementadas usando sys_clone ).

Código-fonte:

#include<stdio.h>
main()
{
        int pid;
        pid=vfork();
}

Saída de ltrace -S :

...
__libc_start_main([some stuff here] <unfinished ...>
vfork([more stuff] <unfinished ...>
SYS_vfork([more stuff])
--- SIGCHLD (Child exited) ---

Existe uma razão pela qual a libc usa SYS_vfork para vfork() mas não usa SYS_fork para fork() ? Eu li a resposta de Thomas Nyman para Qual arquivo no kernel especifica fork (), vfork ()… para usar a chamada do sistema sys_clone () , que diz:

vfork() in turn is implemented via a separate CLONE_VFORK flag, which will cause the parent process to sleep until the child process wakes it via a signal. The child will be the sole thread of execution in the parent's namespace, until it calls exec() or exits. The child is not allowed to write to the memory. The corresponding clone() call could be as follows:

clone(CLONE_VFORK | CLONE_VM | SIGCHLD, 0)

Isto parece estar em desacordo com o que eu observei da saída de ltrace -S .

Eu estraguei alguma coisa ou os escritores deliberadamente escolheram implementar vfork() usando SYS_vfork em vez de SYS_clone por um motivo? Isso é considerado algo que pode mudar a qualquer momento ou podemos confiar nele?

    
por user2108462 26.03.2018 / 23:52

2 respostas

4

Did I mess something up or did the glibc writers deliberately choose to implement vfork() using SYS_vfork instead of SYS_clone for a reason?

Historicamente, acho mais provável que isso seja simplesmente o resultado de vfork não precisar ser alterado. Tanto vfork como fork usaram inicialmente as chamadas de sistema equivalentes. Quando a segmentação NPTL foi implementada, a implementação fork foi alterada para usar clone , porque a biblioteca C precisa redefinir o ID do encadeamento . vfork não precisa se preocupar com os tópicos, porque ele é destinado apenas ao uso com execve (que redefinirá todo esse estado de qualquer maneira), por isso não foi alterado.

O documento de projeto NPTL explica por que a chamada do sistema fork não é suficiente para implementar o fork chamada de biblioteca quando os threads podem ser usados:

To implement the fork function without memory leaks it is necessary that the memory used for stacks and other internal information of all threads except the thread calling fork is reclaimed. The kernel cannot help in this situation.

Is this considered something that could change at any time or can we rely on it?

Como você usa a biblioteca C como bifurcação, só pode confiar na biblioteca C que fornece o comportamento documentado nas APIs. você não pode confiar em uma implementação específica. Você não deve confiar em vfork(3) usando a chamada de sistema vfork(2) em vez de clone(2) , nem deve confiar em fork(3) usando clone(2) em vez de fork(2) . Note que as chamadas do sistema que são usadas podem variar de uma arquitetura para outra ...

Se você realmente precisar confiar em chamadas específicas do sistema, você deve usá-las diretamente e abrir mão dos invólucros da biblioteca C.

    
por 27.03.2018 / 00:59
2

man 2 fork :

C library/kernel differences
Since version 2.3.3, rather than invoking the kernel's fork() system call, the glibc fork() wrapper that is provided as part of the NPTL threading implementation invokes clone(2) with flags that provide the same effect as the traditional system call. (A call to fork() is equivalent to a call to clone(2) specifying flags as just SIGCHLD.) The glibc wrapper invokes any fork handlers that have been established using pthread_atfork(3).

    
por 27.03.2018 / 00:50