Qual é a diferença entre fork () e vfork ()?

13

Gostaria de entender em detalhes a diferença entre fork () e vfork (). Não fui capaz de digerir a página de manual completamente.

Eu também gostaria de esclarecer que um dos meus colegas comentou " No Linux atual, não há vfork (), mesmo que você o chame, ele chamará internamente de fork () ".

Sen
fonte

Respostas:

24

As páginas de manual geralmente são documentos de referência concisos. A Wikipedia é um lugar melhor para obter explicações conceituais.

Fork duplica um processo: ele cria um processo filho quase idêntico ao processo pai (a diferença mais óbvia é que o novo processo tem um ID de processo diferente). Em particular, o fork (conceitualmente) deve copiar toda a memória do processo pai.

Como isso é bastante caro, o vfork foi inventado para lidar com um caso especial comum em que a cópia não é necessária. Freqüentemente, a primeira coisa que o processo filho faz é carregar uma nova imagem do programa, e é isso que acontece:

if (fork()) {
    # parent process …
} else {
    # child process (with a new copy of the process memory)
    execve("/bin/sh", …);  # discard the process memory
}

A execvechamada carrega um novo programa executável e isso substitui o código do processo e a memória de dados pelo código do novo executável e uma nova memória de dados. Portanto, toda a cópia de memória criada por forkfoi inútil.

Assim, a vforkligação foi inventada. Não faz uma cópia da memória. Portanto, vforké barato, mas é difícil de usar, pois você precisa garantir que não acessa nenhum espaço de pilha ou pilha do processo no processo filho. Observe que mesmo a leitura pode ser um problema, porque o processo pai continua em execução. Por exemplo, esse código está quebrado (pode ou não funcionar, dependendo de o filho ou o pai obter uma fatia de tempo primeiro):

if (vfork()) {
    # parent process
    cmd = NULL; # modify the only copy of cmd
} else {
    # child process
    execve("/bin/sh", "sh", "-c", cmd, (char*)NULL);  # read the only copy of cmd
}

Desde a invenção do vfork, melhores otimizações foram inventadas. A maioria dos sistemas modernos, incluindo o Linux, usa uma forma de copiar na gravação , em que as páginas na memória do processo não são copiadas no momento da forkchamada, mas mais tarde quando o pai ou o filho primeiro escreve na página. Ou seja, cada página começa como compartilhada e permanece compartilhada até que qualquer processo seja gravado nessa página; o processo que escreve obtém uma nova página física (com o mesmo endereço virtual). A cópia na gravação torna o vfork praticamente inútil, pois forknão fará nenhuma cópia nos casos em vforkque seria utilizável.

O Linux retém o vfork. A forkchamada do sistema ainda deve fazer uma cópia da tabela de memória virtual do processo, mesmo se não copiar a memória real; vforknem precisa fazer isso. A melhoria de desempenho é insignificante na maioria dos aplicativos.

Gilles 'SO- parar de ser mau'
fonte
1
Obrigado por esta resposta brilhante. Ao fazer o fork (), o filho de qualquer maneira obterá um novo ID de processo e seu espaço virtual associado; por que ainda deve fazer uma cópia da tabela de memória virtual do processo? Eu não sou claro nessa parte.
Sen
@Sen: forkprecisa criar um mapeamento de memória virtual separado para que cópias subsequentes de cópia na gravação afetem apenas um dos dois processos.
Gilles 'SO- stop be evil'
tem certeza de que o processo pai está em execução?
Qbolec 23/10/2014
2

Os syscalls fork()e vfork()são diferentes.

O fork()syscall gera dois processos idênticos com memória separada. O vfork()syscall gera dois processos que compartilham a mesma memória.

Com vfork()o pai esperará que o filho termine. O pai herda das variáveis ​​que o programa está compartilhando. Então, depois que o filho foi chamado, todas as variáveis ​​modificadas dentro do filho ainda serão modificadas dentro do pai.

Para mais informações clique aqui

Yogeesh HT
fonte