por que áreas privadas do mapa de funções execvas?

Sep 24 2020

Eu estava lendo um livro que descreve nossa execvefunção como:

Suponha que o programa em execução no processo atual faça a seguinte chamada:

execve("a.out", NULL, NULL);

a função execve carrega e executa o programa contido no arquivo-objeto executável a.out dentro do processo atual, substituindo efetivamente o programa atual pelo programa a.out. Carregar e executar a.out requer as seguintes etapas

  1. Excluir áreas de usuário existentes
  2. Mapeie áreas privadas. Crie novas estruturas de área para as áreas de código, dados, bss e pilha do novo programa. Todas essas novas áreas são cópia na gravação privada como:

  1. Mapear áreas compartilhadas
  2. Defina o contador do programa

Estou um pouco confuso sobre a etapa 2, então digamos que fork()bifurque um processo filho e deixe o processo filho ser executado execvepara um novo programa, então por que execvemapear as novas áreas do processo filho como cópia na gravação privada? o processo pai não compartilha memória com o processo filho porque os processos pai e filho são mapeados para objetos diferentes. Por que o processo filho tem medo de que outros processos gravem sth para afetá-lo?

Respostas

1 R..GitHubSTOPHELPINGICE Sep 25 2020 at 00:06

Nesse contexto, o mapeamento privado é oposto ao mapeamento compartilhado. Um mapeamento compartilhado gravável do arquivo exigiria acesso de gravação ao arquivo e quaisquer alterações nele seriam refletidas no disco e em todos os outros mapeamentos compartilhados do arquivo, incluindo outras instâncias do mesmo programa ou biblioteca. Obviamente, isso não é desejado.

Isso é para mapeamentos de arquivos / bibliotecas executáveis. Para coisas como bss que não têm backup de arquivo (mapas "anônimos"), você pode se perguntar por que um mapeamento compartilhado não pode ser usado. Na verdade, seria até que o processo bifurcasse, mas se você bifurcar, o mapeamento anônimo compartilhado seria compartilhado entre o pai e o filho. Às vezes, você deseja fazer isso intencionalmente para mapas com os quais você mesmo cria mmap, mas isso não fornece a semântica correta para objetos de dados globais após a bifurcação, portanto, não pode ser usado aqui.

4 ShadowRanger Sep 24 2020 at 21:30

Se você olhar o diagrama, a maioria dessas páginas de "cópia na gravação privada" são páginas de "demanda zero". É assim que o Linux lida com as solicitações de alocação; ele copy-on-write mapeia a página zero. Portanto, se você apenas ler a página, verá que ela está cheia de zeros, mas não ocupa a memória real nesse ponto. Assim que você precisa escrever para ele, ele cria uma nova página "real" perfeitamente preenchida com zeros e aplica sua escrita a ela.

Para o restante deles, como a .dataseção, é o mapeamento nos dados originais do executável, mas você não gostaria de modificar o arquivo no disco porque reatribuiu uma variável global, então, novamente, o copy-on-write é usado.

Basicamente, não se trata de "copiar" uma página real do programa original , é apenas uma estratégia para servir páginas zeradas de forma consistente para o programa a partir do sistema operacional e fornecer acesso barato aos dados do executável original de uma forma que permita modificações, se necessário.