Eu sei que quando uma página de cache de página é modificada, ela é marcada como suja e requer um write-back, mas o que acontece quando:
Cenário: O arquivo /apps/EXE, que é um arquivo executável, é paginado completamente no cache da página (todas suas páginas estão em cache/memória) e sendo executado pelo processo P
A liberação contínua substitui /apps/EXE por um novo executável.
Suposição 1: suponho que o processo P (e qualquer outra pessoa com um descritor de arquivo referenciando o executável antigo) continuará usando o antigo, na memória /apps/EXE sem problemas, e qualquer novo processo que tentar executar esse caminho obterá o novo executável.
Suposição 2: Presumo que, se nem todas as páginas do arquivo forem mapeadas na memória, tudo ficará bem até que haja uma falha de página exigindo páginas do arquivo que foram substituídas e provavelmente ocorrerá uma falha de segmentação?
Pergunta 1: Se você bloquear todas as páginas do arquivo com algo como vmtouch, isso altera o cenário?
Pergunta 2: Se /apps/EXE estiver em um NFS remoto, isso faria alguma diferença? (presumo que não)
Por favor, corrija ou valide minhas 2 suposições e responda minhas 2 perguntas.
Vamos supor que esta é uma caixa CentOS 7.6 com algum tipo de kernel 3.10.0-957.el7
Atualização: Pensando mais sobre isso, gostaria de saber se esse cenário não é diferente de qualquer outro cenário de página suja.
Suponho que o processo que escreve o novo binário fará uma leitura e obterá todas as páginas de cache, pois todas as páginas serão paginadas e, em seguida, todas essas páginas serão marcadas como sujas. Se eles estiverem bloqueados, eles serão apenas páginas inúteis ocupando a memória central depois que a contagem de referências chegar a zero.
Eu suspeito que quando os programas atualmente em execução terminarem, qualquer outra coisa usará o novo binário. Supondo que tudo esteja correto, acho que só é interessante quando apenas parte do arquivo é paginado.
Essa é a parte importante.
A forma como um novo arquivo é lançado é criando um novo arquivo (por exemplo
/apps/EXE.tmp.20190907080000
), escrevendo o conteúdo, configurando permissões e propriedade e finalmente renomeando(2) para o nome final/apps/EXE
, substituindo o arquivo antigo.O resultado é que o novo arquivo tem um novo número de inode (o que significa, na verdade, é um arquivo diferente).
E o arquivo antigo tinha seu próprio número de inode, que na verdade ainda existe , mesmo que o nome do arquivo não esteja mais apontando para ele (ou não há mais nomes de arquivo apontando para esse inode).
Então, a chave aqui é que quando falamos sobre "arquivos" no Linux, na maioria das vezes estamos falando sobre "inodes", já que uma vez que um arquivo é aberto, o inode é a referência que mantemos para o arquivo.
Correto.
Incorreta. O inode antigo ainda está disponível, portanto, as falhas de página do processo usando o binário antigo ainda poderão encontrar essas páginas no disco.
Você pode ver alguns efeitos disso observando o
/proc/${pid}/exe
link simbólico (ou, equivalentemente,lsof
a saída) do processo executando o binário antigo, que mostrará/app/EXE (deleted)
para indicar que o nome não está mais lá, mas o inode ainda está por aí.Você também pode ver que o espaço em disco usado pelo binário só será liberado depois que o processo morrer (assumindo que é o único processo com esse inode aberto.) Verifique a saída de
df
antes e depois de matar o processo, você o verá cair pelo tamanho daquele velho binário que você achava que não existia mais.BTW, isso não é apenas com binários, mas com qualquer arquivo aberto. Se você abrir um arquivo em um processo e remover o arquivo, o arquivo será mantido no disco até que o processo feche o arquivo (ou morra). o driver do sistema de arquivos (no kernel do Linux) mantém um contador de quantas referências existem para aquele inode na memória e só liberará o inode do disco quando todas as referências do sistema em execução também forem liberadas.
Esta questão é baseada na suposição incorreta 2 de que não bloquear as páginas causará falhas de segmentação. Não vai.
Ele deve funcionar da mesma maneira e na maioria das vezes funciona, mas existem algumas "pegadinhas" com o NFS.
Às vezes, você pode ver os artefatos de excluir um arquivo que ainda está aberto no NFS (aparece como um arquivo oculto nesse diretório).
Você também tem alguma maneira de atribuir números de dispositivo às exportações NFS, para garantir que eles não sejam "reorganizados" quando o servidor NFS for reinicializado.
Mas a ideia principal é a mesma. O driver do cliente NFS ainda usa inodes e tentará manter os arquivos (no servidor) enquanto o inode ainda for referenciado.
Não, isso não acontecerá, porque o kernel não permitirá que você abra para escrever ou substituir qualquer coisa dentro de um arquivo que esteja atualmente em execução. Tal ação falhará com
ETXTBSY
[1] :Quando o dpkg, etc atualiza um binário, ele não o substitui, mas usa
rename(2)
o que simplesmente aponta a entrada do diretório para um arquivo completamente diferente, e quaisquer processos que ainda tenham mapeamentos ou alças abertas para o arquivo antigo continuarão a usá-lo sem problemas .[1] a
ETXBUSY
proteção não se estende a outros arquivos que também podem ser considerados "texto" (= live code/executável): bibliotecas compartilhadas, classes java, etc; modificar tal arquivo enquanto mapeado por outro processo fará com que o processo falhe. No linux, o vinculador dinâmico obedientemente passa oMAP_DENYWRITE
sinalizador parammap(2)
, mas não se engane - não tem nenhum efeito. Exemplo:A resposta de filbranden está correta, supondo que o processo de liberação contínua faça a substituição atômica adequada de arquivos via
rename
. Se não, mas modifica o arquivo no local, as coisas são diferentes. No entanto, seu modelo mental ainda está equivocado.Não há possibilidade de as coisas serem modificadas no disco e serem inconsistentes com o cache da página, porque o cache da página é a versão canônica e a que foi modificada. Quaisquer gravações em um arquivo ocorrem por meio do cache de página. Se já estiver presente, as páginas existentes serão modificadas. Se ainda não estiver presente, as tentativas de modificar uma página parcial farão com que toda a página seja armazenada em cache, seguida pela modificação como se já estivesse armazenada em cache. Escritas que abrangem uma página inteira ou mais podem (e quase certamente o fazem) otimizar a etapa de leitura paginando-as. .
(*) Eu menti um pouco. Para NFS e outros sistemas de arquivos remotos, pode haver mais de um, e eles normalmente (dependendo de qual e de quais opções de montagem e do lado do servidor são usadas) não implementam corretamente a atomicidade e a semântica de ordenação para gravações. É por isso que muitos de nós os consideramos fundamentalmente quebrados e nos recusamos a usá-los para situações em que haverá gravações simultâneas ao uso.