AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 787802
Accepted
learningtech
learningtech
Asked: 2024-12-08 06:09:18 +0800 CST2024-12-08 06:09:18 +0800 CST 2024-12-08 06:09:18 +0800 CST

Compreendendo os conceitos de comandos, processos e namespaces

  • 772

Não sou um usuário forte de Linux, mas quero entender melhor o material neste post aqui que fala sobre namespaces Linux

https://stackoverflow.com/questions/44666700/unshare-pid-bin-bash-fork-cannot-allocate-memory

Acho que minha incapacidade de compreensão pode estar relacionada à compreensão insuficiente de "comando", "processo" e talvez algumas outras coisas.

Primeiro, deixe-me explicar um experimento simples que estou usando para minha educação. Abri duas janelas de terminal PUTTY. Em cada janela, fiz um ssh root@[ip of machine]. Agora que tenho 2 sessões SSH para minha máquina Linux, começo meus experimentos.

Na primeira janela, fiz isso:

root@localhost:~# unshare --pid /bin/bash
bash: fork: Cannot allocate memory

Na segunda janela, fiz isso:

root@localhost:~# ps -aux | grep unshare
root       58188  0.0  0.0   6480  2284 pts/3    R+   21:49   0:00 grep --color=auto unshare

Aqui estão minhas perguntas:

  1. A segunda janela não mostra nenhuma indicação de unshare --pid /bin/bash. Isso ocorre porque o /bin/bashcomando ou o /bin/bashprocesso já havia terminado? É por isso que muitos usuários de Linux na internet recomendam usar o --forkpara que o /bin/bashseja executado no namespace recém-criado?

  2. A resposta aceita declarou isto: "Depois que o bash começar a rodar, o bash irá bifurcar vários novos subprocessos para fazer algumas coisas." Não entendi o significado desta frase. Então, na segunda janela do terminal, eu rodei isto:

root@localhost:~# unshare -pf /bin/bash
root@localhost:~# ps -a
    PID TTY          TIME CMD
  58278 pts/2    00:00:00 sudo
  58279 pts/2    00:00:00 su
  58280 pts/2    00:00:00 bash
  58291 pts/2    00:00:00 unshare
  58292 pts/2    00:00:00 bash
  58299 pts/2    00:00:00 ps

PID 58278 a PID58299 é o que o autor quis dizer com "o bash bifurcará vários novos subprocessos para fazer algumas coisas"?

process
  • 1 1 respostas
  • 46 Views

1 respostas

  • Voted
  1. Best Answer
    Andy Dalton
    2024-12-08T10:41:51+08:002024-12-08T10:41:51+08:00

    Fundo

    Começarei com um histórico simplificado sobre como os processos são criados no Linux. Não cobrirei todas as opções ou todos os detalhes, mas, em vez disso, focarei nas ideias principais.

    Geralmente, novos processos são criados usando a fork()chamada do sistema. Em caso de sucesso, fork()resultará em um novo processo que está executando o mesmo programa que o original (efetivamente, é um clone do programa que foi invocado fork()no ponto em que chamou fork()). A fork()função retorna tanto no processo "pai" quanto no processo "filho" (o recém-criado). Cada processo pode examinar o valor de retorno de fork()para determinar se é o "pai" ou o "filho", e pode usar isso para decidir o que fazer em seguida.

    Muitas vezes, criar um novo processo significa que queremos executar um programa diferente, e até agora só temos uma maneira de criar cópias do mesmo programa. Felizmente, há uma chamada de sistema separada, exec(), que substitui o programa em execução no momento por um novo programa.

    Considere o caso em que você tem um shell (vou assumir bashaqui) e você digita lspara listar o conteúdo do diretório atual:

    (P1:bash) calls fork()
    --- the kernel creates P2 that is a copy of P1
    --- the kernel starts running P2
    
    (P1:bash) fork() returns with the PID of P2, so it knows it's the parent
    (P1:bash) Waits for P2 to finish (detailed elided)
    
    (P2:bash) fork() returns with 0, so it knows is the child
    (P2:bash) calls exec("ls")
    --- the kernel replaces bash with ls in P2 and starts ls running
    
    (P2:ls) starts running
    ...
    (P2:ls) eventually terminates
    
    (P1:bash) wakes up since P2 is finished, continues about its business
    

    O Problema

    Você começa com:

    # unshare --pid /bin/bash
    bash: fork: Cannot allocate memory
    bash-5.2#
    

    Observe o erro bash: fork: Cannot allocate memory– isso não é um bom sinal.

    Neste caso, o unshareprograma (1) cria um novo namespace PID e (2) execs /bin/bash. Lembre-se da seção Background que exec substitui o processo em execução atual ( unshare) por um novo programa ( /bin/bash) – ele não cria um novo processo.

    Até agora, nenhum processo está sendo executado no namespace PID recém-criado. O namespace existe, mas o processo que o criou ainda não fez fork()-ed em nada.

    À medida que bashcomeça a ser executado, ele normalmente executa algum conjunto de programas. Aqui runestá a combinação fork/ execdescrita na seção Background. O kernel coloca o primeiro processo que bash fork()s no novo namespace PID e esse processo se torna o initprocesso para esse namespace (o processo nesse namespace com pid = 1). O programa que bashé executado provavelmente tem vida curta, então ele é executado, termina e o namespace PID é destruído.

    Em seguida, bashtenta executar algum outro comando. Ele quer colocar esses comandos no novo namespace PID, mas esse namespace PID não existe mais. Como resultado, ele fork()falha resultando na mensagem de erro que você vê. Você verá isso novamente se tentar executar qualquer outro comando:

    bash-5.2# ls
    bash: fork: Cannot allocate memory
    bash-5.2#
    

    A solução

    Como você observou em sua pergunta, o unshareprograma tem outra opção que é útil neste cenário. De man unshare:

    -f, --fork

    Bifurque o programa especificado como um processo filho unshareem vez de executá-lo diretamente. Isso é útil ao criar um novo namespace PID. Observe que quando unshareestá esperando pelo processo filho, ele ignora SIGINTe SIGTERMe não encaminha nenhum sinal para o filho. É necessário enviar sinais para o processo filho.

    Você pode substituir seu primeiro comando por:

    # unshare --fork --pid /bin/bash
    #
    

    Observe que neste caso não há erro.

    Esta opção faz com unshareque seu comportamento seja alterado. Em vez de usar imediatamente exec()para substituir a si mesmo por /bin/bash, ele usa o comportamento fork()/ exec()descrito na seção Background acima:

    (P1:unshare) calls fork()
    --- the kernel creates P2 that is a copy of P1
    --- the kernel starts running P2
    
    (P1:unshare) fork() returns with the PID of P2, so it knows it's the parent
    (P1:unshare) Waits for P2 to finish (detailed elided)
    
    (P2:unshare) fork() returns with 0, so it knows is the child.
    --- P2 is running in the new PID namespace and has pid = 1
    
    (P2:unshare) calls exec("/bin/bash")
    --- the kernel replaces unshare with /bin/bash in P2 and starts ls running
    
    (P2:bash) starts running
    

    Você pode confirmar que neste caso /bin/bashé o initprocesso (ou seja, processo com pid 1) imprimindo seu id de processo:

    # echo $$
    1
    #
    

    Respostas para suas perguntas

    1. A segunda janela não mostra nenhuma indicação de unshare --pid /bin/bash. Isso ocorre porque o /bin/bashcomando ou o /bin/bashprocesso já havia terminado? É por isso que muitos usuários Linux na internet recomendam usar o --forkpara que o /bin/bashseja executado no namespace recém-criado?

    A segunda janela não mostra nenhuma indicação de unshareque não está mais em execução – ela costumava exec()ser substituída por /bin/bash.

    A --forkopção altera o comportamento de unsharepara que ele fork()primeiro crie um novo processo — um processo no namespace PID recém-criado — e então esse processo o usa exec()para se substituir por /bin/bash.

    1. A resposta aceita declarou isto: "Depois que o bash começar a rodar, o bash irá bifurcar vários novos subprocessos para fazer algumas coisas." Não entendi o significado desta frase. Então, na segunda janela do terminal, eu rodei isto:

    Os novos subprocessos provavelmente terão vida curta, então eles não estarão mais em execução quando você executar o ps.

    • 2

relate perguntas

  • Como substituir os IDs de usuário e IDs de grupo por nomes em vez de números em "ps"?

  • Como obter os IDs dos grupos suplementares de um processo?

  • O que `/proc/irq/.../spurious` contém?

  • Um processo pai pode alterar o ambiente de seu filho?

  • Como 'ejetar' obtém processos para fechar identificadores de arquivo?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve