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

130

Li em livros de texto que o Unix / Linux não permite links físicos para diretórios, mas permite links físicos. É porque, quando temos ciclos e se criamos links físicos, e depois de algum tempo excluímos o arquivo original, ele aponta 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, por que os links físicos para diretórios são permitidos?

user3539
fonte
2
Para onde ..apontar? Especialmente depois de remover o link físico para este diretório, no diretório apontado por ..? Precisa apontar para algum lugar.
Thorbjørn Ravn Andersen
2
..não precisa existir fisicamente em nenhuma unidade. De qualquer forma, é tarefa do sistema operacional acompanhar o diretório de trabalho atual; portanto, deve ser relativamente simples manter também uma lista de inodes associados ao cwd de cada processo e referir-se a ele quando usar ... Obviamente, isso significaria que links simbólicos precisariam ser criados com isso em mente, mas você já deve ter cuidado para não quebrar links simbólicos, e eu não acho que essa regra adicional os torne inúteis.
Parthian Shot
Eu gosto dessa explicação . Conciso e fácil de ler e / ou roçar.
Trevor Boyd Smith

Respostas:

143

Essa é apenas uma péssima idéia, pois não há como distinguir entre um link físico e um nome original.

Permitir links físicos para diretórios quebraria a estrutura gráfica acíclica direcionada do sistema de arquivos, possivelmente criando loops de diretório e subárvores de diretório pendentes, o que tornaria fsckqualquer outro caminhante da á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. Os inodes não possuem nomes de arquivos. É 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 os dois nomes de arquivos apontem para o 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, testou test2, qual é o arquivo original e qual é o link físico? No final, você não pode realmente dizer (mesmo com registros de data e hora) porque os dois 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

A -ibandeira para lsmostra os números de inode no início da linha. Observe como teste test2tenha o mesmo número de inode, mas test3tem um número diferente.

Agora, se você pudesse fazer isso para diretórios, dois diretórios diferentes em pontos diferentes no sistema de arquivos poderiam apontar para a mesma coisa. De fato, um subdir poderia apontar de volta para seu avô, criando um loop.

Por que esse loop é uma preocupação? Porque quando você está percorrendo, não há como detectar que você está fazendo um loop (sem acompanhar os números dos inodes enquanto você percorre). Imagine que você está escrevendo o ducomando, que precisa se repetir nos subdiretórios para descobrir sobre o uso do disco. Como dusaberia quando atingisse um loop? É propenso a erros e muita contabilidade dudeveria ser feita, apenas para executar esta tarefa simples.

Os links simbólicos são um animal totalmente diferente, pois são um tipo especial de "arquivo" que muitas APIs de sistema de arquivos tendem a seguir automaticamente. Observe que um link simbólico pode apontar para um destino inexistente, porque aponta pelo nome e não diretamente para um inode. Esse conceito não faz sentido com links físicos, porque a mera existência de um "link físico" significa que o arquivo existe.

Então, por que dulidar com links simbólicos com facilidade e não com links físicos? Pudemos ver acima que os links físicos são indistinguíveis das entradas normais do diretório. Os links simbólicos, no entanto, são especiais, detectáveis ​​e ignoráveis!  dupercebe que o link simbólico é um link simbólico e o ignora 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    .
Danny Dulai
fonte
7
Allowing hard links to directories would break the directed acyclic graph structure of the filesystem. Você pode explicar mais sobre o problema dos ciclos usando links físicos? Por que está tudo bem com links simbólicos
user3539 12/12
33
Eles parecem ter permitido isso nos Macs, adicionando detecção de ciclo à chamada do sistema link () e recusando-se a permitir que você crie um link físico de diretório, se isso criar um ciclo. Parece ser uma solução razoável.
psusi
10
@psusi mkdir -pa / b; nocheckln ca; mv ca / ​​b; - o nocheckln existe um ln teórico que não verifica os argumentos do diretório e apenas passa para o link, e como nenhum ciclo é feito, somos todos bons em criar 'c'. em seguida, passamos 'c' para 'a / b', e um ciclo é criado a partir de um / b / c -> a / - check-in link () não é bom o suficiente
Danny Dulai
3
Ciclos são muito ruins. O Windows tem esse problema com "junções", que são diretórios de link físico. Se você aplicar acidentalmente permissões em todo o perfil, ele descobrirá uma série de junções que criam um ciclo infinito. A recorrência nos diretórios se repete até que as limitações de tamanho do caminho o interrompam.
doug65536
4
@WhiteWinterWolf, de acordo com este link, eles adicionaram suporte especificamente para a máquina do tempo, mas somente o root pode fazer isso: superuser.com/questions/360926/…
psusi
14

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

Uma maneira de fazer pwdé verificar o dispositivo: inode para '.' e '..'. Se eles forem iguais, você alcançou a raiz do sistema de arquivos. Caso contrário, encontre o nome do diretório atual no pai, coloque-o em uma pilha e comece a comparar '../.' com '../ ..', depois '../../.' com '../../ ..', etc. Depois de acessar a raiz, comece a exibir e imprimir os nomes da pilha. Esse algoritmo baseia-se no fato de que cada diretório possui um e apenas um pai.

Se links físicos para diretórios forem permitidos, qual dos vários pais deve ..apontar? Essa é uma razão convincente pela qual links físicos para diretórios não são permitidos.

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

Joe Inwap
fonte
3
Não tenho tanta certeza disso. Se considerarmos ..uma espécie de link físico virtual para o pai, não há razão técnica para que o destino do link possa ter apenas outro link para ele. pwdprecisaria usar um algoritmo diferente para resolver o caminho.
precisa saber é o seguinte
13

Você pode usar o mount mount para simular diretórios de link físico

sudo mount --bind /some/existing_real_contents /else/dummy_but_existing_directory
sudo umount /else/dummy_but_existing_directory
zainengineer
fonte
7

Eu gostaria de acrescentar mais alguns pontos sobre esta questão. Links físicos para diretórios são permitidos no linux, mas de maneira restrita.

Uma maneira 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 possui o diretório "b" como filho.

 a
 `-- b

Anote o inode do diretório "a". E quando fazemos um ls -ladiretório "a", podemos ver isso "." O 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" possui três links físicos. Isso ocorre porque o inode 797358 possui três hardlinks no nome de "." dentro do diretório "a" e nomeie como ".." dentro do diretório "b" e um com o nome "a" em si.

$ 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 ..

Portanto, aqui podemos entender que os hardlinks existem apenas para os diretórios se conectarem aos diretórios pai e filho. E assim, um diretório sem filho terá apenas 2 hardlink, e o diretório "b" terá apenas dois hardlink.

Uma razão pela qual a vinculação forçada de diretórios foi impedida livremente seria evitar loops de referência infinitos, que confundirão 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.

Kannan Mohan
fonte
11
Bom exemplo. Isso esclareceu minha dúvida. Portanto, esses casos são tratados de uma maneira especial para evitar loops infinitos. direito?
G Gill
11
Como temos uma maneira limitada de permitir links físicos para diretórios, ou seja, ".." e "." nós não vamos chegar a um loop infinito e por isso não necessita de quaisquer maneiras especiais para evitar aqueles como eles não acontecerá :)
Kannan Mohan
6

Nenhuma das seguintes é a verdadeira razão para não permitir links físicos para diretórios; cada problema é bastante fácil de resolver:

  • ciclos na estrutura da árvore causam dificuldades
  • pais múltiplos, então qual é o "real"?
  • coleta de lixo do sistema de arquivos

O verdadeiro motivo (como sugerido por @ Thorbjørn Ravn Andersen) ocorre quando você exclui um diretório que possui vários pais, do diretório apontado por ..:

O que ..agora deve apontar?

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

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, então os designers decidiram não permitir.

Lqueryvg
fonte
3
Isso também é fácil de resolver: mantenha uma lista de pais de um diretório filho, que você atualiza quando adiciona ou remove um link para o filho. Quando você exclui o pai canônico (o destino do filho ..), atualize ..para apontar para um dos outros pais na lista.
jathd
2
Concordo. Não é ciência de foguetes a resolver. Mas, no entanto, uma sobrecarga de desempenho e ocuparia um pouco de espaço extra nos metadados do sistema de arquivos e aumentaria a complexidade. E assim os designers adotaram a abordagem simples e rápida - não permitam links para diretórios físicos.
precisa saber é o seguinte
11
Os links Sym para dirs "violam comportamentos e semânticas estabelecidas", mas ainda são permitidos. Alguns comandos, portanto, precisam de opções para controlar se os links sym são seguidos (por exemplo, -L em find e cp). Quando um programa segue '..', há mais confusão, daí a diferença na saída de pwd e / bin / pwd após atravessar um link sym. Não há "respostas para Unix"; apenas projete decisões. Este gira em torno do que acontece com "..", como afirmei na minha resposta. Infelizmente, '..' nem é mencionado na resposta pela qual todos os outros estão votando tão timidamente.
Lqueryvg
BTW, não estou dizendo que sou a favor de links físicos para dirs. De modo nenhum. Não quero que meu trabalho diário seja mais difícil do que já é.
Lqueryvg
Não é o que o POSIX diz, mas o IMO '..' nunca deveria ter sido um conceito de sistema de arquivos, mas sim resolvido sintaticamente nos caminhos, o que a/..sempre significaria .. É assim que os URLs funcionam, btw. É o navegador que está resolvendo '..' antes mesmo de atingir o servidor. E funciona muito bem.
ybungalobill
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 ele /dir2.

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

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

E se eu excluir recursivamente em /dir2... será excluído /dir1também!

IMHO é uma razão amplamente suficiente para evitar isso!

Editar:

Os comentários sugerem a remoção do diretório, fazendo rm-o. Mas rmem um diretório não vazio falha, e esse comportamento deve permanecer, independentemente de o diretório estar vinculado ou não. Então você não pode simplesmente rmdesvincular. Seria necessário um novo argumento para rm, apenas para dizer "se o inode do diretório tiver uma contagem de referência> 1, desvinculará apenas o diretório".

O que, por sua vez, quebra outro princípio de menor surpresa: significa que a remoção de um hardlink de diretório que acabei de criar não é a mesma coisa que a remoção de um hardlink de arquivo normal ...

Vou reformular minha frase: sem desenvolvimento adicional, a criação de links físicos seria irreversível (já que nenhum comando atual poderia lidar com a remoção sem ser incoerente com o comportamento atual)

Se permitirmos que mais desenvolvimento lide com o caso, o número de armadilhas e o risco de perda de dados, se você não estiver ciente de como o sistema funciona, como implica esse desenvolvimento, o IMHO é uma razão suficiente para restringir a vinculação de diretórios.

Pierre-Olivier Vares
fonte
Isso não deve ser um problema. No seu caso, quando criamos o hardlink para o dir2, precisamos criar um hardlink para todo o conteúdo no dir1 e, se renomearmos ou excluirmos o dir2, apenas um link extra para o inode será excluído. E isso não deve afetar o dir1 e seu conteúdo, pois existe pelo menos um link (dir1) para o inode.
precisa saber é o seguinte
3
Seu argumento está incorreto. Você simplesmente desvincularia isso, não faça rm -rf. E se a contagem de links atingir 0, o sistema saberá que também pode excluir todo o conteúdo.
LtWorf
Isso é mais ou menos tudo rmque existe por baixo (desvincular). Veja: unix.stackexchange.com/questions/151951/… Isso realmente não é um problema, assim como acontece com os arquivos com links físicos . Desvincular apenas remove a referência nomeada e diminui a contagem de links. O fato de rmdirnão excluir diretórios não vazios é irrelevante - não faria isso dir1 também. Os hardlinks não são cópias de dados, eles são o mesmo arquivo real; portanto, "excluir" o arquivo dir2 apagaria a listagem de diretórios do dir1. Você sempre precisaria desvincular.
BryKKan
Você não pode simplesmente desvinculá-lo como um arquivo normal, porque rmem um diretório não desvincule-o se não estiver vazio. Veja Editar.
Pierre-Olivier Vares 12/07
1

Esta é uma boa explicação. Em relação a "Qual dos vários pais deve .. apontar?" uma solução seria que um processo mantivesse seu caminho wd completo, como inodes ou como uma string. inodes seria mais robusto, pois os nomes podem ser alterados. Pelo menos nos dias antigos, havia um inode no núcleo para cada arquivo aberto que era incrementado sempre que um arquivo era aberto, diminuído quando fechado. Quando chegasse a zero, o armazenamento apontado seria liberado. Quando o arquivo não era mais aberto por ninguém, ele (a cópia dentro do núcleo) seria abandonado. Isso manteria o caminho 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,

Os diretórios de link físico costumavam ser permitidos livremente no Bell Labs UNIX, pelo menos V6 e V7. Não conheça Berkeley ou posterior. Não é necessário sinalizador. Você poderia fazer loops? Sim, não faça isso. É muito claro o que você está fazendo se fizer um loop. Nether, você deve praticar um nó no pescoço enquanto aguarda a 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 com isso hoje era ligar o lhome a casa para que eu pudesse ter / home / administ disponível, independentemente de / home estar coberto com um automout sobre home, esse automount com um link simbólico chamado administ para / lhome / administ. Isso me permite ter uma conta administrativa que funcione independentemente do estado do meu sistema de arquivos inicial principal. Este é um experimento para linux, mas acho que aprendi ao mesmo tempo para o SunOS baseado em UCB que as montagens automáticas são feitas no nível de string 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 .. também não existem arquivos no diretório Estou certo de que existem boas razões para tudo isso e que muito do que desfrutamos (como poder montar o NTFS) é possível por causa disso, mas parte da elegância do UNIX estava na implementação. São os benefícios, como generalidade e maleabilidade, que essa elegância proporcionou que lhe permitiu ser tão robusta e durar quatro décadas. À medida que perdemos as implementações elegantes, ele se tornará o Windows (espero estar 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. ele é Por incrível que pareça, o quão aplicável é o entendimento de 30 anos no Linux ... na maioria das vezes!

user57607
fonte
Eu acho que, embora possa estar errado, isso .e ..não são hardlinks no sistema de arquivos dos sistemas de arquivos modernos. No entanto, o driver do sistema de arquivos os falsifica. São esses sistemas de arquivos que interrompem os diretórios de link físico. Para sistemas de arquivos antigos, era possível (mas perigoso). Para fazer o que você está tentando mount --bind, veja também mount --make…e talvez contêineres.
Ctrl-alt-delor
0

Pelo que entendi, o principal motivo é que é útil poder alterar os nomes de diretório sem atrapalhar os programas em execução que usam seu diretório de trabalho para referenciar outros arquivos. Suponha que você estivesse usando o Wine para executar ~/.newwineprefix/drive_c/Program Files/Firefox/Firefox.exee desejasse mover o prefixo inteiro para ~/.wineele. Se por alguma razão estranha Firefox estava acessando drive_c/windows, referindo-se ../../windows, renomeando ~/.newwineprefixbreaks implementações de ..que manter o controle do diretório pai como uma cadeia de texto em vez de um inode.

Armazenar o inode de um diretório pai único deve ser mais simples do que tentar rastrear todos os caminhos como uma sequência de texto e uma série de inodes.

Outro motivo é que aplicativos com comportamento inadequado podem criar loops. Os aplicativos com comportamento devem poder verificar se o inode do diretório que está sendo movido é igual ao inode de qualquer diretório aninhado para o qual está sendo movido, assim como você não pode mover um diretório para si mesmo, mas isso pode não ser imposto. no nível do sistema de arquivos.

Ainda outro motivo pode ser o fato de que, se você pudesse vincular diretórios a diretórios, desejaria impedir a vinculação de um diretório que não pôde modificar. findpossui 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 findestiver chamando outro comando. Ser capaz de vincular diretórios importantes forçaria um administrador a adicionar testes extras findpara evitar afetá-los. (Ok, você já não pode fazer isso para arquivos, portanto, este motivo é inválido.)

Outro motivo é que o armazenamento do inode do diretório pai pode fornecer redundância extra em caso de corrupção ou dano no sistema de arquivos. Se você deseja ..listar todos os diretórios-pai que possuem um link direto para este, para que um pai arbitrário diferente possa ser facilmente encontrado se o atual for desvinculado, você não apenas estará violando a ideia de que os links físicos são iguais, mas também como sistema de arquivos armazena e usa inodes. O fato de os programas tratarem os caminhos como uma série (exclusiva para cada link físico) de inodes de diretório evitaria isso, mas você não obteria a redundância em caso de danos no sistema de arquivos.

Misaki
fonte