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

11

Digamos que se eu digitar cd no meu shell. cd está carregado da memória nesse momento? Minha intuição é que esses comandos embutidos são pré-carregados na memória do sistema depois que o kernel foi carregado, mas alguém insistiu que eles são carregados apenas quando eu realmente invoco o comando (pressione enter em um shell). Você poderia, por favor, me dizer se há uma referência que explique isso?

    
por Forethinker 14.09.2013 / 19:05

4 respostas

9

Let's say if I type in cd in my shell. Is cd loaded from the memory at that moment? My intuition is that these built-in commands are pre-loaded to the system memory after the kernel has been loaded, but someone insisted that they are loaded only when I actually invoke the command...

Em termos gerais, as outras respostas estão corretas - os built-ins são carregados com o shell, os stand-alones são carregados quando invocados. No entanto, uma doninha muito grosseira "alguém" poderia 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 eu acho que, em geral, o seguinte é provavelmente verdadeiro para todos os enigmas contemporâneos.

Primeiro, "carregado na memória" é uma frase ambígua; realmente o que estamos nos referindo é tem 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 é inicialmente: principalmente o que é realmente carregado na memória é o próprio mapa - e < strong> o mapa não é o território. O "território" seria o executável no disco (ou no cache de disco) e, na verdade, a maior parte provavelmente não é carregado na memória quando você invoca um executável.

Além disso, muito do "território" refere-se a outros territórios (bibliotecas compartilhadas) e, novamente, apenas porque eles foram mencionados não significa que eles também estejam realmente carregados. Eles não são carregados até que sejam realmente usados, e somente os pedaços deles que realmente precisam ser carregados para que qualquer "uso" seja bem sucedido.

Por exemplo, aqui está um snippet de top output no linux referente a uma bash instance:

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

A VIRT de 113 MB é o espaço de endereço virtual, que é mapeado na RAM. Mas RES é a quantidade real de RAM consumida pelo processo - apenas 3,7 kB. E disso, parte é parte do território compartilhado mencionado acima - 1.8 kB SHR. Mas o meu /bin/bash no disco é 930 kB, e a biblioteca básica com links para (uma biblioteca compartilhada) tem o dobro do tamanho novamente.

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

Isso é chamado de demanda de paginação .

    
por 14.09.2013 / 21:08
9

Enquanto aguarda a chegada de um dos pesos-pesados e dê uma perspectiva histórica completa, darei a você minha compreensão mais limitada.

Comandos incorporados como alias , cd , echo etc fazem parte do seu shell ( bash , zsh , ksh ou qualquer outro). Eles são carregados ao mesmo tempo em que o shell é e são simplesmente funções internas desse shell.

    
por 14.09.2013 / 19:20
4

Eu fiz o seguinte experimento para mostrar que os comandos internos são de fato carregados como parte do bash exectuable. Daí porque eles são chamados de builtins, mas uma demonstração é sempre a melhor maneira de provar algo.

Exemplo

  1. Inicie um novo bash shell e observe seu ID de processo (PID):

    $ bash
    $ echo $$
    6402
    
  2. Em um segundo terminal, execute o comando ps para que possamos assistir e ver se bash começa a ocupar qualquer memória adicional:

    $ 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 com o SZ & Colunas RSS aqui.

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

    À medida que você cd , você notará que a memória realmente sobe, mas isso não é por causa do executável cd sendo carregado na memória, e sim porque a estrutura de diretórios do disco está sendo carregada na memória. Se você mantiver cd 'em outros diretórios, verá incrementalmente.

    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 subirá um nível e voltará para o diretório 90609 1000 vezes. Ao executar isso, se você monitorar o uso da memória na janela ps , perceberá que isso não muda. Ao executar algo como isto, nenhum uso de memória adicional deve ser notado.

  4. strace

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

    $ strace cd ..
    strace: cd: command not found
    
por 14.09.2013 / 21:17
3

"comando interno" refere-se a comandos embutidos no shell, em vez de 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 de disco.

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

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

    
por 14.09.2013 / 19:19