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

12

Eu gostaria de entender em detalhes a diferença entre fork () e vfork (). Não consegui digerir completamente a página do manual.

Eu também gostaria de esclarecer um dos meus colegas comentar " No Linux atual, não há vfork (), mesmo se você chamá-lo, ele irá chamar internamente fork () ."

    
por Sen 02.01.2011 / 16:39

2 respostas

22

As páginas do manual são geralmente documentos de referência concisa. O Wikipedia é um lugar melhor para recorrer a explicações conceituais.

Fork duplica um processo: ele cria um processo filho que é quase idêntico ao processo pai (a diferença mais óbvia é que o novo processo tem um ID de processo diferente). Em particular, 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. Muitas vezes, a primeira coisa que o processo filho faz é carregar uma nova imagem do programa, então é 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 chamada execve 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 por uma nova memória de dados. Assim, toda a cópia da memória criada por fork foi tudo para nada.

Assim, a vfork chamada foi inventada. Não faz uma cópia da memória. Portanto, vfork é barato, mas é difícil de usar, pois você precisa ter certeza de que não acessará nenhuma pilha ou espaço de pilha do processo no processo filho. Note que mesmo a leitura pode ser um problema, porque o processo pai continua executando. Por exemplo, este código está corrompido (pode ou não funcionar dependendo se o filho ou o pai receber 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 copy-on-write , onde as páginas do a memória do processo não é copiada no momento da chamada fork , mas posteriormente quando o pai ou filho primeiro grava na página. Ou seja, cada página começa como compartilhada e permanece compartilhada até que o processo grave nessa página; o processo que grava obtém uma nova página física (com o mesmo endereço virtual). Copy-on-write torna o vfork praticamente inútil, já que fork não fará nenhuma cópia nos casos em que vfork possa ser usado.

O Linux retém o vfork. A chamada de sistema fork ainda deve fazer uma cópia da tabela de memória virtual do processo, mesmo que não copie a memória real; vfork nem precisa fazer isso. A melhoria de desempenho é insignificante na maioria das aplicações.

    
por 02.01.2011 / 17:33
2

As fork() e vfork() syscalls 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 aguardará o término do filho. 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

    
por 08.12.2015 / 07:40