Os arquivos são abertos por processos carregados na RAM?

Os arquivos são abertos por processos carregados na RAM?

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 dodisco rígidoé colocado noBATER, onde eles ganham vida e podem fazer coisas e são chamadosprocessos.

Os processos podem fazer uso de outros arquivos, ler ou escrever neles e, se o fizerem, esses arquivos 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 e outro na RAM, também se aplica a outros tipos de arquivos, por exemplo aqueles que não têm lógica programada, mas são simplesmente contêineres para dados.

Minha suposição é 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?

Responder1

Não, um arquivo não é lido automaticamente na memória ao abri-lo. Isso seria terrivelmente ineficiente. sed, por exemplo, lê sua entrada linha por linha, assim como muitas outras ferramentas Unix. Raramente é necessário manter mais do que a linha atual na memória.

Com awké a mesma coisa. Ele lê umregistrode 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

for line in $(cat file); do ...; done

Como o shell terá que expandir $(cat file)completamente a substituição do comando antes mesmo de executar a primeira iteração do forloop, issovaileia tudo filena memória (na memória usada pelo shell que executa o forloop). Isso é um pouco bobo e também deselegante. Em vez disso, deve-se fazer

while IFS= read -r line; do ...; done <file

Isto irá processar filelinha por linha (mas leiaCompreendendo "IFS = read -r line").

Processar arquivos linha por linha no shell raramente é necessário, já que a maioria dos utilitários são orientados a linhas de qualquer maneira (vejaPor que usar um loop de shell para processar texto é considerado uma prática inadequada?).

Estou trabalhando com bioinformática e, ao processar grandes quantidades de dados genômicos, não seria capaz de fazer muito a menos que mantivesse na memória apenas os bits de dados que eram absolutamente necessários. Por exemplo, quando preciso retirar os bits de dados que poderiam 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 isso linha por linha processamento com um awkprograma simples (isso é possível porque o formato VCF é orientado a linhas). EUnãoleia o arquivo na memória, processe-o lá e grave-o novamente! Se o arquivo fosse compactado, eu o alimentaria por meio de zcator gzip -d -c, que, como gzipfaz o processamento de dados em fluxo, também não leria o arquivo inteiro na memória.

Mesmo com formatos de arquivo que sãonãoorientados a linhas, como JSON ou XML, existem analisadores de fluxo que possibilitam processar arquivos enormes sem armazenar tudo na RAM.

Com executáveis, é um pouco mais complicado, pois bibliotecas compartilhadas podem ser carregadas sob demanda e/ou compartilhadas entre processos (vejaCarregamento de bibliotecas compartilhadas e uso de RAM, por exemplo).

Cache é algo que não mencionei aqui. Esta é a ação de usar RAM para armazenar dados acessados ​​com frequê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 cache, assim como o buffer de entrada e saída, geralmente é bastante transparente para o usuário e a quantidade de memória usada para armazenar coisas em cache pode 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 por vez, usando buffer explícito ou implicitamente através do buffer que as bibliotecas de E/S padrão fazem, e então apresentam esse pedaço linha por linha ao código do usuário. É muito mais eficiente ler um múltiplo do tamanho do bloco do disco do que, por exemplo, um caractere por vez. No entanto, esse tamanho de bloco raramente será maior que alguns kilobytes.

Responder2

Entretanto, quando os comandos estão sendo executados, uma cópia de seus arquivos do disco rígido é colocada na RAM,

Isso está errado (em geral). Quando um programa é executado (atravésexecutivo(2)...) o processo (executando esse programa) está mudando suaespaço de endereço virtuale o kernel está reconfigurando oMMUpara aquele propósito. Leia também sobrememória virtual. Observe que os programas aplicativos podem alterar seu espaço de endereço virtual usandomapa(2)& munmap&mproteger(2), também utilizado pelovinculador dinâmico(verld-linux(8)). Veja tambémlouco(2)&posix_fadvise(2)&mllock(2).

Futurofalhas de páginaserá processado pelo kernel para carregar páginas (preguiçosamente) do arquivo executável. Leia também sobresurra.

O kernel mantém um grandecache de página. Leia também sobrecopiar na gravação. Veja tambémleitura antecipada (2).

OK, então o que me pergunto é se a vida dupla de um comando, um no disco rígido e outro na RAM, também se aplica a outros tipos de arquivos, por exemplo aqueles que não têm lógica programada, mas são simplesmente contêineres para dados.

Parachamadas do sistemacomoleia (2)&escrever (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 o disco IO for necessário, os dados lidos provavelmente serão colocados no cache da página. Então, 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 giratório antigo - não um SSD - você poderá ouvir isso; ou observe atentamente o LED do seu disco rígido).

Recomendo a leitura de um livro comoSistemas operacionais: três peças fáceis(para download gratuito, um arquivo PDF por capítulo) que explica tudo isso.

Veja tambémLinux comeu minha RAMe execute comandos como xosview, top, htopou cat /proc/self/mapsou cat /proc/$$/maps(vejaprocesso(5)).

PS. Estou me concentrando no Linux, mas outros sistemas operacionais também possuem memória virtual e cache de página.

Responder3

Embora ter gigas de RAM hoje em dia seja fantástico, houve um tempo em que a RAM era um recurso muito limitado (aprendi a programar em um VAX 11/750 com 2 MB de RAM) e a única coisa na RAM eram executáveis ​​ativos e páginas de dados. de processos ativos e dados de arquivo que estavam no cache do buffer.
O cache do buffer foi esvaziado 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 marcadas para que, se o programa tocasse nessas páginas novamente, elas fossem paginadas a partir do sistema de arquivos. Os dados foram paginados a partir do swap. Conforme observado acima, a biblioteca STDIO extraiu dados em blocos e foram obtidos pelo programa conforme necessário: fgetc, fgets, fread, etc. Com mmap, um arquivo pode ser mapeado no espaço de endereço de um processo, como é feito com objetos de biblioteca compartilhados ou até mesmo arquivos regulares. Sim, você pode ter algum grau de controle se está na RAM ou não (mlock), mas só vai até certo ponto (veja a seção de código de erro do mlock).

informação relacionada