Quando chamar fork () e exec () por conta própria?

8

Sou novo em chamadas ao sistema Unix e estou aprendendo sobre os comandos fork () e exec (). Parece que fork () e exec () são geralmente chamados juntos. (fork () cria um novo processo filho e exec () substitui a imagem do processo atual por uma nova.) No entanto, em quais cenários você pode chamar cada função sozinha? Existem cenários como esses?

    
por quil 18.10.2017 / 20:18

4 respostas

21

Claro! Um padrão comum em programas "wrapper" é fazer várias coisas e depois substituir-se por algum outro programa com apenas uma chamada exec (sem fork)

#!/bin/sh
export BLAH_API_KEY=blub
...
exec /the/thus/wrapped/program "$@"

Um exemplo real disso é GIT_SSH (embora git(1) também ofereça GIT_SSH_COMMAND se você não quiser fazer o método do programa wrapper acima).

O Fork-only é usado ao gerar vários processos tipicamente de trabalho (por exemplo, Apache httpd no modo fork (embora o fork seja mais adequado para os processos que precisam queimar a CPU e não para os que estão esperando pela rede) E / S para acontecer)) ou para separação de privilégios usada por sshd e outros programas no OpenBSD (sem exec)

$ doas pkg_add pstree
...
$ pstree | grep sshd
 |-+= 70995 root /usr/sbin/sshd
 | \-+= 28571 root sshd: jhqdoe [priv] (sshd)
 |   \-+- 14625 jhqdoe sshd: jhqdoe@ttyp6 (sshd)

O root sshd tem na conexão do cliente bifurcado uma cópia de si mesmo (28571) e, em seguida, outra cópia (14625) para a separação de privilégio.

    
por 18.10.2017 / 20:42
13

Existem muitos.

Os programas que chamam fork() sem exec() geralmente seguem um padrão de processos de trabalho de geração para executar várias tarefas em processos separados do processo principal. Você encontrará isso em programas tão variados quanto dhclient , php-fpm e urxvtd .

Um programa que chama exec() sem fork() é carregamento de cadeia , sobrepondo seu processo com uma imagem de programa diferente. Há toda uma subcultura de utilitários de carregamento de cadeia que fazem coisas específicas para processar o estado e, em seguida, executam outro programa para executar com esse estado de processo revisado. Esses utilitários são comuns na família de daemontools de conjuntos de ferramentas de gerenciamento de sistemas e serviços, mas não estão limitados a eles. Alguns exemplos:

Os conjuntos de ferramentas da família daemontools têm muito de tais ferramentas, a partir de machineenv através de find-matching-jvm para runtool .

    
por 18.10.2017 / 21:04
2

Além de outras respostas, os depuradores, usando ptrace , costumam usar a lacuna entre fork e exec . Um debuggee deve se marcar com PTRACE_TRACEME para indicar que está sendo rastreado pelo processo pai - o depurador. Isso é para dar permissões necessárias ao depurador.

Assim, um depurador primeiro se separaria. O filho chamaria ptrace com PTRACE_TRACEME e, em seguida, chamaria exec . Qualquer que seja o programa, o filho será agora rastreável pelos pais.

    
por 19.10.2017 / 07:17
0

exec sem garfo

Existem pelo menos dois motivos pelos quais você gostaria de fazer uma coisa dessas:

  1. Carregamento em cadeia. A imagem atual do processo é substituída por algo diferente.
  2. Reiniciando o programa em execução no momento (pode acontecer, por exemplo, quando você SIGHUP ou esse processo do servidor, recarregando tudo e fazendo um novo início completamente). De alguma forma, pode-se argumentar que isso é um carregamento em cadeia, apenas coincidentemente com o mesmo programa.

fork sem exec

Isso é o que todo daemon faz toda vez que é iniciado (duas vezes, na verdade). Isso faz várias coisas, entre elas o shell não trava (já que o processo original que o shell aguarda ao terminar) e o daemon não é mais controlado pelo terminal, então fechar a janela do shell não mata o daemon.

Outro uso comum é o fork de crianças trabalhadoras, que ficou famoso pelo servidor web apache há 25 anos (hoje em dia isso não é mais considerado estado da arte devido a ser muito propenso ao problema do rebanho, mas com certeza fornece o mais simples e robusto servidor possível).

No entanto, outro uso comum é criar um instantâneo consistente. fork não apenas cria um processo, mas também copia (em teoria, na realidade, apenas marca as páginas copy-on-write) o espaço de endereço. Isso (atomicamente) cria um instantâneo dos dados completos do programa que o pai não pode mais modificar.
Alguns programas aproveitam isso. Por exemplo, o redis salva dados no disco (em um estado consistente) enquanto ao mesmo tempo modifica o conjunto de dados ao mesmo tempo. Isso só funciona porque fork criou um instantâneo consistente que não vê as modificações feitas pelo processo pai.

    
por 19.10.2017 / 20:32