Por que links físicos para diretórios não são permitidos no UNIX / Linux?

124

Eu li em livros de texto que o Unix / Linux não permite links para diretórios, mas permite links suaves. É porque, quando temos ciclos e se criamos hard links, e depois de algum tempo nós deletamos o arquivo original, ele apontará para algum valor de lixo?

Se os ciclos foram a única razão por trás da não permissão de links físicos, então por que os links para diretórios são permitidos?

    
por user3539 11.10.2011 / 06:21

8 respostas

135

Esta é apenas uma má ideia, já que não há como diferenciar um link físico de um nome original.

Permitir links rígidos para diretórios quebraria a estrutura do gráfico acíclico direcionado do sistema de arquivos, possivelmente criando loops de diretórios e subárvores de diretório pendentes, o que tornaria o fsck e qualquer outro passeador de árvore de arquivos propenso a erros.

Primeiro, para entender isso, vamos falar sobre inodes. Os dados no sistema de arquivos são mantidos em blocos no disco, e esses blocos são coletados juntos por um inode. Você pode pensar no inode como o arquivo. Inodes não possuem nomes de arquivos, no entanto. É aí que entram os links.

Um link é apenas um ponteiro para um inode. Um diretório é um inode que contém links. Cada nome de arquivo em um diretório é apenas um link para um inode. Abrir um arquivo no Unix também cria um link, mas é um tipo diferente de link (não é um link nomeado).

Um link físico é apenas uma entrada de diretório extra apontando para esse inode. Quando você ls -l , o número após as permissões é a contagem de links nomeados. A maioria dos arquivos regulares terá um link. Criar um novo link físico para um arquivo fará com que ambos os nomes apareçam no mesmo inode. Nota:

% ls -l test
ls: test: No such file or directory
% touch test
% ls -l test
-rw-r--r--  1 danny  staff  0 Oct 13 17:58 test
% ln test test2
% ls -l test*
-rw-r--r--  2 danny  staff  0 Oct 13 17:58 test
-rw-r--r--  2 danny  staff  0 Oct 13 17:58 test2
% touch test3
% ls -l test*
-rw-r--r--  2 danny  staff  0 Oct 13 17:58 test
-rw-r--r--  2 danny  staff  0 Oct 13 17:58 test2
-rw-r--r--  1 danny  staff  0 Oct 13 17:59 test3
            ^
            ^ this is the link count

Agora, você pode ver claramente que não existe um link físico. Um link físico é o mesmo que um nome comum. No exemplo acima, test ou test2 , que é o arquivo original e qual é o link físico? No final, você não pode dizer (mesmo por timestamps) porque ambos os nomes apontam para o mesmo conteúdo, o mesmo inode:

% ls -li test*  
14445750 -rw-r--r--  2 danny  staff  0 Oct 13 17:58 test
14445750 -rw-r--r--  2 danny  staff  0 Oct 13 17:58 test2
14445892 -rw-r--r--  1 danny  staff  0 Oct 13 17:59 test3

O -i flag para ls mostra os números de inode no início da linha. Observe como test e test2 têm o mesmo número de inode, mas test3 tem um diferente.

Agora, se você tivesse permissão para fazer isso para diretórios, dois diretórios diferentes em pontos diferentes no sistema de arquivos poderiam apontar para a mesma coisa. Na verdade, um subdir poderia apontar de volta para seu avô, criando um loop.

Por que esse loop é uma preocupação? Porque quando você está atravessando, não há como detectar que você está em loop (sem manter o controle dos números de inodes à medida que você atravessa). Imagine que você está escrevendo o comando du , que precisa recorrer aos subdiretórios para descobrir o uso do disco. Como du saberia quando atingisse um loop? É propenso a erros e muita contabilidade que du teria que fazer, apenas para executar essa tarefa simples.

Os links simbólicos são uma coisa totalmente diferente, pois são um tipo especial de "arquivo" que muitas APIs do sistema de arquivos tendem a seguir automaticamente. Observe que um link simbólico pode apontar para um destino inexistente, porque eles apontam por nome e não diretamente para um inode. Esse conceito não faz sentido com hard links, porque a mera existência de um "hard link" significa que o arquivo existe.

Então, por que o du pode lidar com links simbólicos facilmente e não com hard links? Pudemos ver acima que os hard links são indistinguíveis das entradas normais de diretório. Os links simbólicos, no entanto, são especiais, detectáveis e ignoráveis! du percebe que o link simbólico é um link simbólico e o pula completamente!

% ls -l 
total 4
drwxr-xr-x  3 danny  staff  102 Oct 13 18:14 test1/
lrwxr-xr-x  1 danny  staff    5 Oct 13 18:13 test2@ -> test1
% du -ah
242M    ./test1/bigfile
242M    ./test1
4.0K    ./test2
242M    .
    
por 11.10.2011 / 10:28
13

Com exceção dos pontos de montagem, cada diretório tem um e apenas pai: .. .

Uma maneira de fazer pwd é verificar o dispositivo: inode para '.' e '..'. Se forem iguais, você atingiu a raiz do sistema de arquivos. Caso contrário, encontre o nome do diretório atual no pai, empurre-o em uma pilha e comece a comparar '../.' com '../ ..', depois '../../.' com '../../ ..', etc. Assim que você atingir a raiz, comece a estalar e imprimir os nomes da pilha. Este algoritmo depende do fato de que cada diretório tem um e apenas um pai.

Se links rígidos para diretórios foram permitidos, qual dos vários pais deve .. apontar? Essa é uma razão convincente para o fato de que hardlinks para diretórios não são permitidos.

Os links simbólicos para os diretórios não causam esse problema. Se um programa quiser, ele pode fazer um lstat() em cada parte do nome do caminho e detectar quando um symlink é encontrado. O algoritmo pwd retornará o caminho verdadeiro absoluto para um diretório de destino. O fato de haver um pedaço de texto em algum lugar (o symlink) que aponta para o diretório de destino é praticamente irrelevante. A existência de tal link simbólico não cria um loop no gráfico.

    
por 24.03.2012 / 00:46
10

Você pode usar o bind mount para simular diretórios de links difíceis

sudo mount --bind /some/existing_real_contents /else/dummy_but_existing_directory
sudo umount /else/dummy_but_existing_directory
    
por 11.04.2016 / 06:45
6

Eu gosto de adicionar mais alguns pontos sobre essa questão. Links rígidos para diretórios são permitidos no linux, mas de forma restrita.

Uma forma de testar isso é quando listamos o conteúdo de um diretório e encontramos dois diretórios especiais "." e "..". Como sabemos "." aponta para o mesmo diretório e ".." aponta para o diretório pai.

Então vamos criar uma árvore de diretórios onde "a" é o diretório pai que tem o diretório "b" como seu filho.

 a
 '-- b

Anote o inode do diretório "a". E quando fazemos um ls -la do diretório "a", podemos ver isso "." diretório também aponta para o mesmo inode.

797358 drwxr-xr-x 3 mkannan mkannan 4096 Sep 17 19:13 a

E aqui podemos descobrir que o diretório "a" tem três links físicos. Isso ocorre porque o inode 797358 tem três hardlinks no nome de "." dentro de "a" diretório e nome como ".." dentro do diretório "b" e um com o nome "a" itslef.

$ ls -ali a/
797358 drwxr-xr-x 3 mkannan mkannan 4096 Sep 17 19:13 .

$ ls -ali a/b/
797358 drwxr-xr-x 3 mkannan mkannan 4096 Sep 17 19:13 ..

Então, aqui podemos entender que hardlinks estão lá apenas para diretórios para se conectar com seus diretórios pai e filho. E assim, um diretório sem um filho só terá 2 hardlink, e assim o diretório "b" terá apenas dois hardlinks.

Um dos motivos pelos quais a vinculação de diretórios foi impedida seria evitar enlaces de referência infinitos que confundiriam programas que atravessam o sistema de arquivos.

Como o sistema de arquivos é organizado como árvore e como a árvore não pode ter referência cíclica, isso deveria ter sido evitado.

    
por 17.09.2014 / 16:04
5

Nenhum dos seguintes é o motivo real para não permitir links rígidos para diretórios; cada problema é bastante fácil de resolver:

  • os ciclos na estrutura da árvore causam um percurso difícil
  • vários pais, então qual é o "real"?
  • coleta de lixo do sistema de arquivos

A razão real (como sugerido por @ Thorbjørn Ravn Andersen) vem quando você elimina um diretório que tem múltiplos pais, do diretório apontado por .. :

O que deve .. apontar agora?

Se o diretório for excluído de seu pai, mas sua contagem de links ainda é maior que 0 então deve haver alguma coisa, em algum lugar ainda apontando para ele. Você não pode deixar .. apontando para nada; muitos programas contam com .. , então o sistema teria que percorrer todo o sistema de arquivos até encontrar a primeira coisa que aponta para o diretório, apenas para atualizar .. . Ou isso, ou o sistema de arquivos tem que manter uma lista de todos os diretórios apontando para um diretório de hard link.

De qualquer forma, isso seria uma sobrecarga de desempenho e uma complicação extra para os metadados e / ou código do sistema de arquivos, para que designers decidiram não permitir isso.

    
por 21.11.2014 / 13:54
3

A criação de hardlinks nos diretórios seria irreversível. Suponha que tenhamos:

/dir1
├──this.txt
├──directory
│  └──subfiles
└──etc

Eu o vinculo a /dir2 .

Então /dir2 agora também contém todos esses arquivos e diretórios

E se eu mudar de idéia? Eu não posso apenas rmdir /dir2 (porque não é vazio)

E se eu excluir recursivamente em /dir2 ... ele será excluído de /dir1 também!

IMHO é uma razão em grande parte suficiente para evitar isso!

    
por 29.07.2014 / 12:05
1

Esta é uma boa explicação. Em relação a "Qual dos vários pais deve .. apontar para?" Uma solução seria que um processo mantivesse seu caminho completo em wd, seja como inodes ou como string. inodes seria mais robusto, pois os nomes podem ser alterados. Pelo menos nos tempos antigos, havia um inode no núcleo para cada arquivo aberto que era incrementado sempre que um arquivo era aberto, decrementado quando fechado. Quando chegasse a zero, o armazenamento apontado seria liberado. Quando o arquivo não estava mais aberto por ninguém, ele (a cópia do núcleo) seria abandonado. Isso manteria o caminho como válido se algum outro processo movesse um diretório para outro diretório enquanto o subdiretório estivesse no caminho de outro processo. Semelhante a como você pode excluir um arquivo aberto, mas ele é simplesmente removido do diretório, mas ainda é aberto para qualquer processo que o tenha aberto.

Diretórios hard-linking costumavam ser livremente permitidos no Bell Labs UNIX, pelo menos V6 e V7, Não sei sobre Berkeley ou mais tarde. Não é necessário sinalizar. Você poderia fazer loops? Sim, não faça isso. É muito claro o que você está fazendo se você fizer um loop. Nether você deve praticar amarração de nó ao redor do seu pescoço enquanto você está esperando sua vez de saltar de um avião se você tiver a outra extremidade convenientemente pendurada em um gancho na cabeça.

O que eu esperava fazer hoje era ligar o lhome a casa para que eu pudesse ter / home / administ disponível se ou não / home estava coberto com um automout sobre casa, esse automount tendo um symlink chamado administ para / lhome / administ. Isso me permite ter uma conta administrativa que funciona independentemente do estado do meu sistema de arquivos inicial principal. Este IS é uma experiência para o Linux, mas acho que aprendi uma vez para o SunOS baseado em UCB que as automontagens são feitas no nível da cadeia ASCII. É difícil ver como eles poderiam ser feitos de outra forma como uma camada sobre qualquer FS arbitrário.

Eu li em outro lugar isso. e .. não são mais arquivos no diretório. Tenho certeza de que há boas razões para tudo isso, e que muito do que gostamos (como a capacidade de montar o NTFS) é possível por causa dessas coisas, mas algumas das elegâncias do UNIX estavam na implementação. São os benefícios, como a generalidade e a maleabilidade que essa elegância proporcionou, que a tornaram robusta e duradoura por quatro décadas. À medida que perdemos as implementações elegantes, ela acabará se tornando como o Windows (espero que eu esteja errado!). Alguém criaria um novo sistema operacional baseado em princípios elegantes. Algo para pensar sobre. Talvez eu esteja errado, não estou (obviamente) familiarizado com a implementação atual. É incrível, mas quão aplicável a compreensão de 30 anos é para o Linux ... na maioria das vezes!

    
por 25.01.2014 / 15:56
0

Pelo que entendi, a principal razão é que é útil poder alterar nomes de diretório sem bagunçar programas em execução que usam seu diretório de trabalho para fazer referência a outros arquivos. Suponha que você estivesse usando o Wine para executar ~/.newwineprefix/drive_c/Program Files/Firefox/Firefox.exe e desejasse mover o prefixo inteiro para ~/.wine . Se por algum motivo estranho o Firefox estava acessando drive_c/windows referindo-se a ../../windows , renomear ~/.newwineprefix quebra implementações de .. que mantêm o controle do diretório pai como uma cadeia de texto em vez de um inode.

Armazenar o inode de um único diretório pai deve ser mais simples do que tentar rastrear cada caminho como uma cadeia de texto e uma série de inodes.

Outra razão é que aplicativos mal-comportados podem criar loops. Comportamento de aplicativos deve ser capaz de verificar se o inode do diretório que está sendo movido é o mesmo que o inode de qualquer um dos diretórios aninhados que está sendo movido, assim como você não pode mover um diretório para si mesmo, mas isso pode não ser aplicado no nível do sistema de arquivos.

No entanto, outra razão pode ser que, se você pudesse vincular diretórios, você evitaria vincular um diretório que não pudesse ser modificado. find tem considerações de segurança porque é usado para limpar arquivos criados por outros usuários de diretórios temporários, o que pode causar problemas se um usuário alternar um diretório real para um link simbólico enquanto find estiver invocando outro comando. Ser capaz de vincular diretórios importantes forçaria um administrador a adicionar testes extras a find para evitar afetá-los. (Ok, você já não pode fazer isso por arquivos, então este motivo é inválido.)

No entanto, outra razão é que o armazenamento do inode do diretório pai pode fornecer redundância extra em caso de corrupção ou danos no sistema de arquivos. Se você quisesse que .. listasse todos os diretórios-pais que possuem um link para esse, então um pai arbitrário diferente poderia ser facilmente encontrado se o atual fosse desvinculado, você não apenas violaria a idéia de que hard links são iguais, você tem que alterar como o sistema de arquivos armazena e usa inodes. Ter programas tratando caminhos como uma série (exclusiva para cada hardlink) de inodes de diretório evitaria isso, mas você não obteria a redundância em caso de danos no sistema de arquivos.

    
por 14.08.2018 / 23:17