No Unix, normalmente, um arquivo é uma entrada em uma tabela de arquivos. Existem diferentes tipos de arquivos: arquivos regulares, dispositivos, links simbólicos, portas, tubos, soquetes, diretórios ...
O número do inode (que você pode ver na saída de ls -i
) é o índice nessa tabela.
Agora, você não acessa arquivos por inode, mas por caminho . Um caminho é uma cadeia de entradas de diretório . Você notará que não estamos falando de pasta, mas de diretório aqui. Porque é o que é um diretório (pense em um diretório de telefone).
Um diretório é um tipo especial de arquivo que dá nomes a vários inodes. Uma entrada de diretório é um mapeamento de um nome para um inode.
Um determinado arquivo (um inode) pode ter mais de um nome em um diretório (assim como pode haver mais de um nome em um número de telefone) e também pode ter nomes (entradas) em mais de um diretório. Esses são chamados de links também conhecidos como links físicos para distinguir com links flexíveis (um tipo especial de arquivo que é um ponteiro para um caminho).
Um arquivo (inode) controla o número de links (de entradas em qualquer diretório) que possui, para que quando o número atingir 0 (quando estiver sendo desvinculado do último diretório em que foi referenciado), ele seja desalocado.
Esse é o número (o número de links) que é exibido na ls -l
saída.
Quando um arquivo não-diretório é criado pela primeira vez (com o open
ou creat
(ou bind
ou mknod
para alguns tipos de arquivos) chamadas do sistema), que é feito através do fornecimento com um caminho para o novo arquivo (como "/a/b"
). O que acontece então é um novo arquivo e o inode é alocado e uma nova entrada é adicionada ao diretório associado ao "a"
nome no "/"
diretório raiz. Esse é o link inicial, portanto a contagem de links é uma.
Mais links podem ser adicionados posteriormente com a link()
chamada do sistema (o ln
comando). E os links podem ser removidos com a unlink()
chamada do sistema (o rm
comando).
Você notará que os arquivos do diretório type geralmente têm um número de links maior ou igual a 2.
Agora, quando você cria um diretório, está chamando a mkdir()
chamada de sistema. Algo como mkdir("/a/b")
. O que ele faz é alocar um novo arquivo do tipo diretório. Nesse novo diretório, ele cria automaticamente duas entradas:
"."
( ponto para diretório ). Qual é um link para si mesmo. Portanto, a contagem de links agora é 1.
".."
(para o diretório do diretório ). Qual é um link para "/a"
. Portanto, a contagem de links "/a"
é incrementada em um
Em seguida, esse novo diretório é vinculado a "/a"
(uma entrada é adicionada "/a"
a ele); portanto, sua contagem de links agora é 2. Se um "/a/b/c"
diretório for criado, devido à ".."
entrada "/a/b/c"
, a contagem de links "/a/b"
se tornará 3.
A maioria dos Unices restringe a criação de links adicionais para um diretório, porque eles podem causar loops problemáticos. Quando eles permitem um link()
diretório, geralmente apenas o superusuário pode fazê-lo.
Alguns sistemas de arquivos, como btrfs
partem dessa estrutura de diretório tradicional. Você notará que a contagem de links nos diretórios nos btrfs
sistemas de arquivos é sempre uma, mesmo que esses diretórios contenham uma "."
entrada com o mesmo número de inode que eles mesmos.
O fato de a contagem de links ser tradicionalmente 2 mais o número de subdiretórios tem seu uso. Por exemplo, em:
find . -name '*.c' -print
Se .
não contém subdiretórios, mas contém milhões de arquivos. Ao verificar a contagem de links de .
, find
pode saber que não há subdiretório. Portanto, tudo o que find
precisa fazer é ler o conteúdo do diretório e relatar as entradas que terminam em .c
(como um grep '\.c$'
arquivo de poucos megabytes, não é grande coisa). Caso contrário, find
seria necessário verificar o tipo de cada arquivo para ver se há diretórios nos quais descer (resultando em tantas lstat()
chamadas do sistema). Obviamente, esse tipo de otimização não funciona btrfs
(embora nas versões modernas do Linux, o tipo de arquivo também seja armazenado na entrada do diretório para alguns sistemas de arquivos (inclusive btrfs
) e retornado pela getdents(2)
chamada do sistema usada para recuperar a lista de entradas em um diretório, entãolstat
ainda não é necessário).