Descritores de Arquivos e Swappiness

O que são Descritores de Arquivos (File-Descriptors) e Swappiness. Veremos na prática como funcionam e em quais casos é necessário alterar os valores.

[ Hits: 191 ]

Por: Buckminster em 30/04/2025


Descritores de Arquivos (File-Descriptors)



Vamos começar com um bla bla bla técnico, mas que é necessário, então procurei amenizar o bla bla bla numa linguagem acessível, senão nem eu entenderia.

Um Descritor de Arquivo (FD - File Descriptor) é um número inteiro não negativo retornado pelo sistema (Linux) quando o acesso para um arquivo é permitido sendo que o processo o usa para referenciar um determinado arquivo aberto. É também chamado de Identificador de Arquivo.

"Arquivo" aqui não é somente um arquivo em si, mas tudo o que acontece quando você utiliza o Linux, quando você abre um programa é criado um descritor de arquivo, uma espécie de índice, também um "cache", veremos mais adiante.

Lembrando que tem esse nome: "descritores de arquivo"; mas para cada programa, ou melhor ainda, para cada coisa, vamos dizer assim, para cada coisa que você faz no Linux é aberto um descritor de arquivo, uma espécie de índice para que não se tenha de lidar com o arquivo propriamente dito. É uma questão de integridade dos dados, isso vem desde o UNIX.

Lembrando aquela máxima (que não é tão verdadeira, mas está valendo): Tudo no Linux é arquivo!

Imagina que você está escrevendo num papel e outra pessoa vem escrever outra coisa nesse mesmo papel... dará bagunça.

Então você escreve no papel e dá uma cópia para outra pessoa corrigir, acrescentar, modificar, etc.

Caso forem muitos papéis você organiza numa tabela e/ou num arquivo quem está com qual papel.

Quando um processo precisa acessar um arquivo ele faz isso através do descritor do arquivo. Os descritores são mantidos pelo Kernel através de uma tabela. O tamanho dessa tabela varia.

Os descritores de arquivo não descrevem exatamente um arquivo, mas sim referenciam e controlam o acesso e modificação dos mesmos.

Os descritores de arquivo de cada processo são controlados pela tabela de "file descriptors" do kernel que por sua vez referenciam arquivos reais nos sistemas de arquivos (ext4, btrfs, etc) utilizados pelo sistema operacional.

Sempre existirá ao menos 1 descritor de arquivo no Kernel para cada arquivo aberto no sistema operacional.

Pode acontecer de um único arquivo ter mais de um descritor.

Caso você esteja procurando uma fórmula mágica para setar os valores dos descritores de arquivo para deixar seu Linux turbinado e extrapolando o hardware da tua máquina, sinto muito, isso não existe, mas deixo aqui uma sugestão para todos que tem um desktop/laptop de uso normal:

NÃO MEXA EM NADA, DEIXE NO PADRÃO! Citarei aqui alguns casos específicos onde se faz necessário alterar os limites.

Servidores Web com Alta Conexão (Apache, Nginx, etc.)

  • Problema: Cada conexão pode usar pelo menos um descritor de arquivo.
  • Sintoma: Erros como "Too many open files".
  • Necessidade: Aumentar o limite para permitir milhares de conexões simultâneas, nesse caso o Linux avisa que você deve aumentar o limite: Too many open files.

Bancos de Dados (PostgreSQL, MySQL, Oracle, etc.)

  • Problema: Conexões simultâneas e manipulação de arquivos de dados e logs consomem muitos FDs (File Descriptors).
  • Necessidade: Bancos como o PostgreSQL recomendam aumentar o limite para centenas de milhares em ambientes de produção.

Aplicações Multithread com Alto I/O

  • Problema: Programas que lidam com muitos arquivos, conexões de rede, pipes ou sockets ao mesmo tempo.
  • Exemplo: Aplicações Java, Node.js ou Python com centenas/milhares de conexões.

Sistemas de Monitoramento, Backup e Indexação (ElasticSearch, Logstash, rsync, etc.)

  • Problema: Precisam manter milhares de arquivos abertos ao mesmo tempo.
  • ElasticSearch, por exemplo, recomenda um limite de 65536 ou mais.

Ambientes de Desenvolvimento com Muitos Arquivos Abertos

  • Problema: Editores de texto como o VSCode, ou compiladores, podem abrir muitos arquivos simultaneamente em grandes projetos.
  • Necessidade: Ajuste para evitar falhas durante builds ou operações em massa.

Cluster de modo geral

Cada processo pode abrir múltiplas conexões de rede para comunicação ponto a ponto.

Em execuções com muitos processos (por exemplo, milhares de ranks), o número de conexões simultâneas cresce exponencialmente.

Além disso, cada processo no cluster pode manter arquivos abertos para logs, checkpoints, e arquivos temporários.

Porém, contudo, todavia, entretanto, caso mesmo assim você queira ou precise modificar os valores, no final desta página tem como fazer isso, resumidamente, com o título MODIFICANDO OS LIMITES.

Vamos executar agora:

cat /proc/sys/fs/file-nr

Exemplo da saída:

11808 0 9223372036854775807

  • O primeiro número é o uso atual que mostra quantos descritores (ou identificadores) de arquivo estão atualmente alocados no sistema inteiro.
  • O segundo valor indica o número de descritores de arquivo alocados, mas não utilizados.
  • O terceiro número indica o número máximo de descritores de arquivo.

O Linux Kernel 2.6 e versões posteriores sempre relatam 0 como o número de descritores de arquivo livres — isso não é um erro, significa apenas que o número de descritores de arquivo alocados corresponde exatamente ao número de identificadores de arquivo utilizados.


Se o primeiro valor estiver perto do terceiro valor é hora de aumentar o número de descritores de arquivo.

Vamos entender esses limites.


A saída de cat /proc/sys/fs/file-max é o valor global máximo de descritores de arquivo que o Kernel alocará - isso é feito para impedir um uso descabido de memória por um processo mal intencionado;
A saída de cat /proc/sys/fs/nr_open é o número máximo de descritores de arquivo que um único processo pode alocar, o valor padrão é 1024*1024 (1048576), o que deve ser suficiente para a maioria das máquinas.
A saída de ulimit (-Sn e -Hn) são os valores por sessão/processo do Shell por usuário.
O parâmetro DefaultlimitNOFILE dentro de /etc/systemd/system.conf define o limite somente para os serviços gerenciados pelo Systemd.
O arquivo /etc/security/limits.conf seta os limites para um usuário em específico.
Vendo o limite atual por sessão do Shell do usuário logado:

ulimit -Sn # soft limit

1024

ulimit -Hn # hard limit

1048576

Ao alterar com "ulimit -n algum_numero" vale somente até fechar o terminal, ou seja, serve para testar se a configuração dará problema.

O comando ulimit no Linux não busca diretamente um arquivo específico, mas ele é influenciado por configurações que podem estar em vários arquivos do sistema, geralmente em /proc//limits.

Essas configurações determinam os limites de recursos para processos do usuário (como número máximo de arquivos abertos, tamanho máximo de arquivos, etc).

Aliás, na própria "man ulimit" avisa que esse comando ficará obsoleto devendo utilizar "prlimit". Veremos adiante os arquivos no diretório /proc.

prlimit -n (-n, --nofile número máximo de arquivos abertos)

RESOURCE DESCRIPTION SOFT HARD UNITS
NOFILE número máximo de arquivos abertos 126639 1048576 arquivos


prlimit -u (-u, --nproc número máximo de processos de usuário)

RESOURCE DESCRIPTION SOFT HARD UNITS
NOFILE número máximo de processos 126639 126639 arquivos


prlimit --help
man prlimit

O limite rígido (hard) é o valor máximo para o limite flexível (soft). Somente usuários root têm permissão para alterar o limite rígido.

É preciso entender que o limite flexível (soft) não é exatamente um limite mínimo, é um limite inicial para o mínimo de arquivos que um processo pode abrir no sistema.

  • O Soft limit pode ser alterado pelo próprio processo — até o valor de hard.
  • O Hard limit só pode ser aumentado pelo root (ou com permissões elevadas - sudo, su, etc).
  • O limite soft é o valor que o Kernel impõe para o recurso correspondente.
  • O limite hard atua como um teto para o limite soft.

Além de tudo tem o Systemd se metendo na parada:

"Os sysctls fs.nr_open e fs.file-max agora são automaticamente elevados para os valores mais altos possíveis, pois a contabilização separada de descritores de arquivo não é mais necessária porque o memcg já os rastreia corretamente como parte da contabilização de memória. Assim, dos quatro limites para descritores de arquivo atualmente aplicados (fs.file-max, fs.nr_open, RLIMIT_NOFILE hard, RLIMIT_NOFILE soft) desativamos os dois primeiros e mantemos apenas os dois últimos."

Veja maiores explicações adiante.

Tudo isso significa que um [i]processo/programa/aplicativo/etc[/i] aberto no Linux tem aqueles limites iniciais e finais para trabalhar, senão o Kernel impede.

Como já visto, os limites globais são os mais altos possíveis. Os outros limites podem ser definidos pelo processo e/ou pelo usuário.

Vemos aí surgir a famosa liberdade do Linux e começamos a entender também porque é muito difícil fazer um malware para Linux mesmo ele tendo seu código fonte aberto a todos.

Vejam bem, falei "difícil", não impossível, mas essa é uma outra discussão que não cabe agora no momento.

Veremos adiante que "malware" pode ser qualquer software que trava/prejudica o sistema, como a própria definição do limite nr_open, como veremos adiante na seção MODIFICANDO OS LIMITES > AVISO IMPORTANTE.

Aconselho a alterar somente o limite global fs.file-max em /etc/sysctl.conf definindo-o com o mesmo valor da saída de "ulimit -Hn" ou "prlimit" na linha NOFILE coluna HARD:

prlimit

RESOURCE DESCRIPTION SOFT HARD UNITS
NOFILE número máximo de arquivos abertos 1024 1048576 arquivos


Como já dito, caso for desktop/laptop de uso diário/cotidiano não precisa alterar nada.

cat /proc/sys/fs/file-max

9223372036854775807

Valor padrão do Kernel automaticamente elevado para o valor mais alto possível. Esse valor mais alto possível é determinado pelos desenvolvedores do Kernel seguindo o bom senso e a experiência.

Grosso modo, caso um [i]processo/programa/aplicativo[i] querer alocar mais de 9.223.372.036.854.775.807 arquivos então obviamente trata-se de um software mal intencionado que quer travar o sistema.

Depois de alterar o /etc/sysctl.conf para, por exemplo, [i]1048576[/i], a saída do comando cat /proc/sys/fs/file-max será [i]1048576[/i]. É preciso reiniciar.

Veremos agora essa tabela no código fonte do Kernel Linux.


A partir da linha 26 do arquivo fdtable.h (Linguagem C):

struct fdtable {
	unsigned int max_fds;
	struct file __rcu **fd;      /* current fd array */
	unsigned long *close_on_exec;
	unsigned long *open_fds;
	unsigned long *full_fds_bits;
	struct rcu_head rcu;
};
Interessante no momento é a variável max_fds que faz o Kernel retornar o erro de "Too many open files" (Muitos arquivos abertos) quando um computador, por exemplo, está com muitos sockets abertos.

Cada processo tem a sua própria tabela de descritores de arquivo, lembrando que todo o Kernel Linux tem a estrutura de "árvore", uma árvore invertida, uma árvore genealógica, basicamente um organograma - processos pais e processos filhos.

Somente para complementar e para não se tornar chato veremos a última parte do arquivo (a partir da linha 107):

struct files_struct *dup_fd(struct files_struct *, struct fd_range *) __latent_entropy;
void do_close_on_exec(struct files_struct *);
int iterate_fd(struct files_struct *, unsigned,
		int (*)(const void *, struct file *, unsigned),
		const void *);

extern int close_fd(unsigned int fd);
extern struct file *file_close_fd(unsigned int fd);

extern struct kmem_cache *files_cachep;
Logo no começo temos ponteiros para files_struct e fd_range com um retorno para uma nova files_struct que é uma duplicata da original.

A função do_close_on_exec fecha os descritores de arquivo marcados com [i]FD_CLOEXEC[/i].

A função iterate_FD itera (executa um bloco de código repetidamente para processar uma coleção de dados) sobre os descritores.

A função close_fd fecha um descritor.

A linha final faz o cache de alocação de memória onde kmem_cache é o gerenciamento de memória eficiente do Kernel Linux.

Na prática quando você clica numa pasta acontece todo esse processo - além de vários outros - e depois você abre um arquivo nessa pasta acontece todo esse processo - além de vários outros - e depois você clica... já deu para entender. Quanto mais arquivos e programas você vai abrindo mais descritores de arquivo são abertos.

Em essência, um descritor de arquivo é uma forma abstrata de identificar um arquivo aberto permitindo ao processo realizar operações sem ter de se preocupar com o nome do arquivo físico.

Os descritores de arquivo 0, 1 e 2 são convencionalmente associados à entrada padrão (stdin), saída padrão (stdout) e saída de erro padrão (stderr), respectivamente.

Entrada padrão (stdin) na prática, basicamente, é quando você tem de digitar seu nome num formulário de cadastro na internet; saída padrão (stdout) é quando abre seu programa depois de clicar no ícone; saída de erro padrão (stderr) são as mensagens de erro, por exemplo, quando aparece "arquivo não encontrado".

Os descritores de arquivo são índices para a tabela do descritor de arquivo na área u_block mantida pelo kernel para cada processo.

Os descritores de arquivo no Linux são armazenados na memória RAM no espaço do Kernel na tabela fdtable; o que fica no disco (HD ou SD) é o arquivo em si com seu conteúdo.

O FD, em uma analogia, pode ser como um número de protocolo que te dão quando você vai num órgão público, ele só serve enquanto você estiver ali. Daí você sai do órgão público e joga fora o papel do protocolo, porém, no órgão fica guardado esse protocolo por um tempo: esse é o cache do descritor de arquivo (kmem_cache).

O Kernel, depois que você fecha um programa, um arquivo, etc, guarda, na maioria das vezes, em /tmp essa informação para que depois seja mais rápido encontrar o programa, o arquivo, etc. Mas veja bem, essa informação é o cache guardado no HD/SD, não é o descritor em si, pois todo descritor é fechado quando você fecha o arquivo. E tem cache na memória RAM e no disco HD ou SSD.

Ao acessar o mesmo arquivo depois de fechá-lo (sem reiniciar o sistema), o sistema busca no cache em disco ou na RAM para ver se tem essa informação e, tendo ou não, ele abre um novo descritor de arquivo na RAM de qualquer maneira.

O que fica no disco são os arquivos de verdade, não essas informações temporárias chamadas "descritores de arquivo".

Quando você reinicia a máquina essa informação no cache desaparece, por isso os programas, arquivos, etc, demoram um pouco mais para abrir.

Quando você desliga a máquina por um bom tempo as coisas demoram mais para iniciar, pois até a memória RAM perdeu as informações.

O reinicio "a quente" é o popular reinicio em si e o reinicio "a frio" é o popular desligamento da máquina.

Lembrando que "cache" é quando você copia ou mantém no lugar certo o que você mais usa para ganhar tempo.

Por exemplo, você deixa a escova e a pasta de dentes no "cache" do armário do banheiro e não na gaveta de talheres da cozinha ou na gaveta de congelados da geladeira.

Suas chaves você costuma deixar perto da porta ou no chaveiro da cintura na calça, ou no seu bolso, na sua bolsa, etc.

A idéia de "cache" em informática é evitar acessar "coisas lentas" umas em relação a outras, por exemplo, o acesso à memória RAM é mais rápido do que o acesso ao disco, então é melhor guardar em cache na RAM, contudo, a RAM tem menos espaço do que o disco e, além disso, é memória de acesso aleatório e temporário, então o sistema tem de lidar com isso e faz cache no disco o que é do disco e cache na RAM o que é da RAM; vai da programação otimizar essa parte e nisso o Linux é imbatível!

Fazendo uma abstração: sua casa é o hardware e sua mente é o sistema tentando otimizar sua casa.

Quando você larga suas chaves num lugar aleatório (randômico) e depois não lembra onde as deixou (não guardou um índice ou um cache porque estava distraído e não era o lugar usual das chaves) podemos dizer que deu um "bug" no sistema e você perde um tempão procurando as chaves e durante esse "tempão" você não consegue entrar em casa (não consegue acessar o hardware).

Um descritor de arquivo ocupa, em média, uns 170 bytes na RAM. Mil descritores abertos ocuparão ~170 KB.

Vamos ver mais na prática ainda.

  1. Abra o terminal.
  2. Crie o arquivo:
  3. $ sudo vim descreve.sh
  4. Utilizei o vim, você use teu editor preferido.

Coloque dentro:

#!/bin/bash

PID=$1
FD_COUNT=$(ls /proc/$PID/fd | wc -l)
MEM_ESTIMATE=$(($FD_COUNT * 170))

echo "Processo $PID tem $FD_COUNT descritores abertos"
echo "Estimativa de memória: $MEM_ESTIMATE bytes (~$(($MEM_ESTIMATE / 1024)) KB)"

Salve e saia.

sudo chmod +x descreve.sh

Para ver o pid temos várias maneiras.

pidof nome_processo

pidof apache2

1020 1019 1018 1017 1016 1015

Ou use o top ou htop:

top

top - 21:53:30 up 3:04, 1 user, load average: 0,21, 0,15, 0,14
Tarefas: 312 total, 1 em exec., 311 dormindo, 0 parado, 0 zumbi
%CPU(s): 3,3 us, 1,7 sy, 0,0 ni, 95,0 id, 0,0 wa, 0,0 hi, 0,0 si, 0,0 st
MB mem : 31752,7 total, 26776,2 free, 3672,2 used, 1808,3 buff/cache
MB swap: 1907,0 total, 1907,0 free, 0,0 used. 28080,5 avail mem
Máx. de tarefas = 0, alterar para (0 é ilimitado) q
PID USUARIO PR NI VIRT RES SHR S %CPU %MEM TEMPO+ COMANDO
2104 aristot+ 20 0 4333536 317508 138132 S 7,3 1,0 2:52.19 cinnamon
4693 aristot+ 20 0 1392,1g 218908 132792 S 7,3 0,7 7:40.18 chrome


Vamos ver o Cinnamon.

sudo ./descreve.sh 2104

Processo 2104 tem 43 descritores abertos
Estimativa de memória: 7310 bytes (~7 KB)


Agora o Chrome:

sudo ./descreve.sh 4693

Processo 4693 tem 52 descritores abertos
Estimativa de memória: 8840 bytes (~8 KB)


E assim você faz para cada [i]PID[/i] que for do seu interesse.

Para ver o [i]PID[/i] do próprio top você terá de abrir outra janela do terminal:

5832 aristot+ 20 0 11804 5532 3364 R 0,3 0,0 0:00.03 top

sudo ./descreve.sh 5852

Processo 5852 tem 6 descritores abertos
Estimativa de memória: 1020 bytes (~0 KB)


Para ver o PID do shell em uso (bash, sh, etc):

echo "O PID do Shell é $$"

O [i]PID[i] do Shell é [i]5864[i]

sudo ./descreve.sh 5864

Processo 5864 tem 4 descritores abertos
Estimativa de memória: 680 bytes (~0 KB)




    Próxima página

Páginas do artigo
   1. Descritores de Arquivos (File-Descriptors)
   2. Descritores de Arquivos
   3. Swappiness
Outros artigos deste autor

Redes de Computadores · IPtables · Endereços IPs - Explicações básicas

Instalação do PAP (PostgreSL, Apache2 e PHP7) no Debian Jessie

Instalar certificado SSL/TLS digital válido gratuito no Linux

Manutenção de sistemas Linux Debian e derivados com apt-get, apt, aptitude e dpkg

Permissões do Linux

Leitura recomendada

Turbinando o Bodhi Linux

Instalando modem LG LM-I56N

VPN Site-to-Site Openswan x ASA (Cisco)

Limitando banda com o CBQ

Preparando o Linux SuSE Enterprise Server 9 para o Oracle 10g R2

  
Comentários

Nenhum comentário foi encontrado.


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts