Quando os comandos internos são carregados na memória

11

Digamos se eu digitar cdmeu shell. É cdcarregado a partir da memória naquele momento? Minha intuição é que esses comandos internos sejam pré-carregados na memória do sistema após o carregamento do kernel, mas alguém insistiu em que eles sejam carregados somente quando eu realmente chamo o comando (pressione enter em um shell). Você poderia me dizer se existe uma referência que explique isso?

Precursor
fonte
1
Acho que essa resposta ajudaria você a entender, embora não seja uma duplicata.
Cjm
@ cjm: Obrigado, foi realmente uma boa explicação para ler.
Forethinker

Respostas:

9

Digamos que se eu digitar cd no meu shell. O CD está carregado na memória naquele momento? Minha intuição é que esses comandos internos sejam pré-carregados na memória do sistema após o carregamento do kernel, mas alguém insistiu em que eles sejam carregados somente quando eu realmente chamo o comando ...

Em termos gerais, as outras respostas estão corretas - os internos são carregados com o shell, os independentes são carregados quando invocados. No entanto, um "alguém" muito exigente pode insistir que não é assim tão simples.

Essa discussão é um pouco sobre como o sistema operacional funciona, e diferentes sistemas operacionais funcionam de maneiras diferentes, mas acho que, em geral, o seguinte provavelmente é verdadeiro para todos os nixes * contemporâneos.

Primeiro, "carregado na memória" é uma frase ambígua; realmente o que estamos nos referindo é que seu espaço de endereço virtual é mapeado na memória . Isso é significativo porque "espaço de endereço virtual" refere-se a coisas que podem precisar ser colocadas na memória, mas na verdade não são inicialmente: principalmente o que é realmente carregado na memória é o próprio mapa - e o mapa não é o território. O "território" seria o executável no disco (ou no cache do disco) e, de fato, a maior parte provavelmente não está carregada na memória quando você invoca um executável.

Além disso, grande parte do "território" é referência a outros territórios (bibliotecas compartilhadas) e, novamente, apenas porque eles foram mencionados, não significa que eles também sejam realmente carregados. Eles não são carregados até que sejam realmente usados, e somente as partes deles que realmente precisam ser carregadas para que "o uso" seja bem-sucedido.

Por exemplo, aqui está um trecho de topsaída no linux referente a uma bashinstância:

VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                  
113m 3672 1796 S  0.0  0.1   0:00.07 bash   

O 113 MB VIRT é o espaço de endereço virtual, mapeado na RAM. Mas RES é a quantidade real de RAM consumida pelo processo - apenas 3,7 kB. E disso, parte faz parte do território compartilhado mencionado acima - 1,8 kB SHR. Mas meu /bin/bashdisco tem 930 kB e a libc básica à qual ela se vincula (uma lib compartilhada) duas vezes maior novamente.

Esse shell não está fazendo nada no momento. Digamos que eu chame um comando interno, que dissemos anteriormente já estava "carregado na memória" junto com o restante do shell. O kernel executa qualquer código envolvido a partir de um ponto no mapa e, quando alcança uma referência ao código que realmente não foi carregado, ele o carrega - de uma imagem executável no disco - mesmo que de maneira mais casual Nesse sentido, esse executável (seja o shell, uma ferramenta independente ou uma biblioteca compartilhada) já estava "carregado na memória".

Isso é chamado de paginação por demanda .

Cachinhos Dourados
fonte
9

Enquanto espero que um dos pesos pesados ​​venha e dê uma perspectiva histórica completa, darei a você meu entendimento mais limitado.

Built-in comandos como alias, cd, echoetc fazem parte de seu escudo ( bash, zsh, kshou qualquer outro). Eles são carregados ao mesmo tempo em que o shell é e são simplesmente funções internas desse shell.

terdon
fonte
4

Fiz o experimento a seguir para mostrar que os comandos internos são, de fato, carregados como parte do executável bash. Por isso, são chamados de builtins, mas uma demonstração é sempre a melhor maneira de provar alguma coisa.

Exemplo

  1. Inicie um novo bashshell e observe seu ID do processo (PID):

    $ bash
    $ echo $$
    6402
    
  2. Em um segundo terminal, execute o pscomando para que possamos observar e ver se bashcomeça a ocupar mais memória:

    $ watch "ps -Fp 6402"
    

    A saída é assim:

    Every 2.0s: ps -Fp 6402                        Sat Sep 14 14:40:49 2013
    
    UID        PID  PPID  C    SZ   RSS PSR STIME TTY          TIME CMD
    saml      6402  6349  0 28747  6380   1 14:33 pts/38   00:00:00 bash
    

    NOTA: O uso da memória é mostrado nas colunas SZ e RSS aqui.

  3. Comece a executar comandos no shell (pid 6402):

    Enquanto você cdobserva, a memória realmente aumenta, mas isso não ocorre devido ao cdcarregamento do executável na memória, mas porque a estrutura de diretórios no disco está sendo carregada na memória. Se você continuar cdem outros diretórios, verá que ele continua aumentando gradualmente.

    Every 2.0s: ps -Fp 30208                        Sat Sep 14 15:11:22 2013
    
    UID        PID  PPID  C    SZ   RSS PSR STIME TTY          TIME CMD
    saml     30208  6349  0 28780  6492   0 15:09 pts/38   00:00:00 bash
    

    Você pode fazer testes mais elaborados como este:

    $ for i in `seq 1000`; do cd ..; cd 90609;done
    

    Este comando aumentará o nível de um cd e depois voltará para o diretório 90609 1000 vezes. Ao executar isso, se você monitorar o uso de memória na psjanela, notará que ele não muda. Ao executar algo parecido com isto, nenhum uso adicional de memória deve ser observado.

  4. traço

    Aqui está outro aviso de que estamos lidando com uma função interna em bashvez de um executável real. Ao tentar executar, strace cd ..você receberá a seguinte mensagem:

    $ strace cd ..
    strace: cd: command not found
    
slm
fonte
3

"comando embutido" refere-se a comandos embutidos no shell, e não como programas separados. ls, por exemplo, na verdade não é um comando interno, mas um programa separado. Ele será carregado na RAM quando for chamado, a menos que já esteja no cache do disco.

Um exemplo de um comando interno seria printfou cd. Eles fazem parte do shell e são carregados junto com o restante do shell.

Nenhum comando é pré-carregado por padrão, embora os sistemas tenham sido criados para fazer isso.

wingedsubmariner
fonte