Comandos , por exemplo sed
, são programas e programas são lógicos codificados dentro de um arquivo e esses arquivos estão em algum lugar do disco rígido. No entanto, quando os comandos estão sendo executados, uma cópia de seus arquivos do disco rígido é colocada na RAM , onde eles ganham vida e podem fazer coisas e são chamados de processos .
Os processos podem fazer uso de outros arquivos, ler ou gravar neles e, se o fizerem, serão chamados de arquivos abertos. Existe um comando para listar todos os arquivos abertos por todos os processos em execução: lsof
.
OK, então o que me pergunto é se a vida dupla de um comando, um no disco rígido, o outro na RAM também é válido para outros tipos de arquivos, por exemplo, aqueles que não têm lógica programada, mas são simplesmente contêineres para dados.
Meu pressuposto é que os arquivos abertos pelos processos também são carregados na RAM. Não sei se é verdade, é apenas uma intuição.
Por favor, alguém poderia entender isso?
Respostas:
Isso está errado (em geral). Quando um programa é executado (através de execve (2) ...), o processo (executando esse programa) está alterando seu espaço de endereço virtual e o kernel está reconfigurando o MMU para esse fim. Leia também sobre memória virtual . Observe que os programas aplicativos podem alterar seu espaço de endereço virtual usando mmap (2) e
munmap
& mprotect (2) , também usados pelo vinculador dinâmico (consulte ld-linux (8) ). Veja também madvise (2) e posix_fadvise (2) e mlock (2) .Falhas de página futuras serão processadas pelo kernel para carregar (preguiçosamente) páginas do arquivo executável. Leia também sobre thrashing .
O kernel mantém um cache de página grande . Leia também sobre copiar na gravação . Veja também readahead (2) .
Para chamadas do sistema como leitura (2) e gravação (2), o cache da página também é usado. Se os dados a serem lidos estiverem nele, nenhuma E / S de disco será feita. Se for necessário E / S de disco, é muito provável que os dados lidos sejam colocados no cache da página. Portanto, na prática, se você executar o mesmo comando duas vezes, pode acontecer que nenhuma E / S física seja feita no disco na segunda vez (se você tiver um disco rígido rotativo antigo - não um SSD), poderá ouvir isso; ou observe cuidadosamente o LED do disco rígido).
Eu recomendo a leitura de um livro como Sistemas operacionais: Three Easy Pieces (que pode ser baixado gratuitamente, um arquivo PDF por capítulo), o que explica tudo isso.
Veja também Linux comeu meus RAM e executar comandos como
xosview
,top
,htop
oucat /proc/self/maps
oucat /proc/$$/maps
(ver proc (5) ).PS. Estou focando no Linux, mas outros sistemas operacionais também têm memória virtual e cache de páginas.
fonte
Não, um arquivo não é lido automaticamente na memória, abrindo-o. Isso seria terrivelmente ineficiente.
sed
, por exemplo, lê sua entrada linha por linha, assim como muitas outras ferramentas Unix. Raramente tem que manter mais do que a linha atual na memória.Com
awk
é o mesmo. Ele lê um registro de cada vez, que por padrão é uma linha. Se você armazenar partes dos dados de entrada em variáveis, isso será extra, é claro 1 .Algumas pessoas têm o hábito de fazer coisas como
Desde que o shell terá de expandir a
$(cat file)
substituição de comando completamente antes de executar até mesmo a primeira iteração dofor
loop, este irá ler integralmentefile
na memória (na memória usada pelo shell de executar ofor
loop). Isso é um pouco bobo e também deselegante. Em vez disso, deve-se fazerIsso processará
file
linha por linha (mas leia Noções básicas sobre "IFS = leia -r linha" ).Porém, raramente é necessário processar arquivos linha por linha no shell, pois a maioria dos utilitários é orientada a linhas (consulte Por que usar um loop do shell para processar o texto considerado uma má prática? ).
Estou trabalhando em bioinformática e, ao processar grandes quantidades de dados genômicos, não seria capaz de fazer muito, a menos que mantivesse apenas os bits dos dados que eram absolutamente necessários na memória. Por exemplo, quando preciso extrair os bits de dados que podem ser usados para identificar indivíduos de um conjunto de dados de 1 terabyte contendo variantes de DNA em um arquivo VCF (porque esse tipo de dados não pode ser tornado público), faço linha por linha processamento com um
awk
programa simples (isso é possível, pois o formato VCF é orientado a linhas). Eu não ler o arquivo na memória, processá-lo lá, e escrevê-lo de volta novamente! Se o arquivo fosse compactado, eu o alimentaria através de ,zcat
ougzip -d -c
, que, comogzip
faz o fluxo de processamento de dados, também não leria o arquivo inteiro na memória.Mesmo com formatos de arquivo que não são orientados a linhas, como JSON ou XML, existem analisadores de fluxo que permitem processar arquivos enormes sem armazenar tudo na RAM.
Nos executáveis, é um pouco mais complicado, pois as bibliotecas compartilhadas podem ser carregadas sob demanda e / ou compartilhadas entre processos (consulte Carregamento de bibliotecas compartilhadas e uso de RAM , por exemplo).
O armazenamento em cache é algo que não mencionei aqui. Esta é a ação de usar a RAM para armazenar dados acessados com freqüência. Arquivos menores (por exemplo, executáveis) podem ser armazenados em cache pelo sistema operacional na esperança de que o usuário faça muitas referências a eles. Além da primeira leitura do arquivo, os acessos subsequentes serão feitos à RAM e não ao disco. O armazenamento em cache, como o buffer de entrada e saída, geralmente é bastante transparente para o usuário, e a quantidade de memória usada para armazenar em cache as coisas podem mudar dinamicamente, dependendo da quantidade de RAM alocada pelos aplicativos etc.
1 Tecnicamente, a maioria dos programas provavelmente lê um pedaço dos dados de entrada de cada vez, usando buffer explícito ou implicitamente através do buffer que as bibliotecas de E / S padrão fazem, e então apresenta esse pedaço de linha por linha no código do usuário. É muito mais eficiente ler um múltiplo do tamanho do bloco do disco do que, por exemplo, um caractere de cada vez. Porém, esse tamanho de pedaço raramente será maior que um punhado de kilobytes.
fonte
awk
,{ a[i++] = $0 }
adicionaria todas as linhas do arquivo de entrada à matriza
. Você também pode procurar a função Cmmap()
, mas seu uso pode ser um pouco fora de tópico aqui.sed
,,awk
e outros programas orientados a linhas não lêem uma linha de cada vez na memória, porque os arquivos de texto sem formatação não contêm um índice de linha, e as APIs do sistema de arquivos e o hardware de armazenamento de baixo nível lêem um ou mais "setores" (normalmente 512 ou 1024 bytes) por vez. Eu ficaria surpreso se menos de 8 KB fossem lidos na memória pelo sistema operacional antes que a primeira linha fosse processada.sed
leia apenas uma linha de cada vez na memória, vale ressaltar que o sistema operacional usará ram grátis para armazenar arquivos em cache, para que possam ser acessados rapidamente. Se você estiver executandosed
em um arquivo menor, é possível que o sistema operacional armazene em cache o arquivo inteiro na memória e a operação seja realizada inteiramente na RAM. Veja: en.wikipedia.org/wiki/Page_cacheNão. Embora tenha shows de RAM hoje em dia seja fantástico, houve um tempo em que a RAM era um recurso muito limitado (eu aprendi a programar em um VAX 11/750 com 2 MB de RAM) e a única coisa na RAM era o executável ativo e as páginas de dados de processos ativos e dados de arquivo que estavam no cache do buffer.
O cache do buffer foi liberado e as páginas de dados foram trocadas. E frequentemente às vezes. As páginas executáveis somente leitura foram sobrescritas e as tabelas de páginas foram marcadas, portanto, se o programa tocasse essas páginas novamente, elas seriam paginadas no sistema de arquivos. Os dados foram paginados a partir da troca. Como observado acima, a biblioteca STDIO coletou dados em blocos e foi obtida pelo programa conforme necessário: fgetc, fgets, fread etc. Com o mmap, um arquivo pode ser mapeado no espaço de endereço de um processo, como é feito com o objetos de biblioteca compartilhada ou mesmo arquivos regulares. Sim, você pode ter algum grau de controle se estiver na RAM ou não (mlock), mas isso só vai tão longe (consulte a seção de código de erro do mlock).
fonte