porque é '.' um link duro no Unix?

51

Eu tenho visto muitas explicações para o porque o link contar para um diretório vazio em sistemas operacionais baseados em Unix é 2 em vez de 1. Todos dizem que é por causa do '. diretório, que cada diretório tem apontando para si mesmo. Eu entendo porque ter algum conceito de '. é útil para especificar caminhos relativos, mas o que é obtido ao implementá-lo no nível do sistema de arquivos? Por que não apenas os shells ou as chamadas do sistema que usam caminhos sabem como interpretá-lo?

Isso '..' é um link real faz muito mais sentido para mim - o sistema de arquivos precisa armazenar um ponteiro de volta para o diretório pai para navegar até ele. Mas eu não vejo porque '. ser um link real é necessário. Também parece que isso leva a um caso especial feio na implementação - você poderia pensar que só poderia liberar o espaço usado pelos inodes que possuem um link menor do que 1, mas se eles são diretórios, você realmente precisa verificar um link conta menos de 2. Por que a inconsistência?

    
por Joseph Garvin 15.10.2011 / 19:09

2 respostas

37

Uma questão interessante, de fato. À primeira vista, vejo as seguintes vantagens:

Primeiro, você afirma que interpretar " . " como o diretório atual pode ser feito pelo Shell ou por chamadas do sistema. Mas ter a entrada de pontos no diretório realmente elimina essa necessidade e força a consistência até mesmo em um nível inferior.

Mas não acho que essa tenha sido a ideia básica por trás dessa decisão de design.

Quando um arquivo está sendo criado ou removido de um diretório, a data e a hora da modificação do diretório também precisam ser atualizadas. Esse registro de data e hora é armazenado em seu inode. O número do inode é armazenado na entrada de diretório correspondente.

SE a entrada do ponto não estaria lá, as rotinas precisariam procurar o número do inode na entrada desse diretório no diretório pai, o que causaria uma busca no diretório novamente.

MAS , felizmente, há a entrada do ponto no diretório atual. A rotina que adiciona ou remove um arquivo no diretório atual só precisa voltar para a primeira entrada (onde a entrada de ponto geralmente reside) e imediatamente encontrou o número de inode para o diretório atual.

Há uma terceira coisa boa sobre a entrada do ponto:

Quando fsck verifica um sistema de arquivos podre e tem que lidar com blocos não conectados que também não estão na lista livre, é fácil verificar se um bloco de dados (quando interpretado como uma lista de diretórios) tem um ponto entrada que está apontando para um inode que por sua vez aponta de volta para este bloco de dados. Nesse caso, esse bloco de dados pode ser considerado como um diretório perdido que precisa ser reconectado.

    
por 16.10.2011 / 00:17
10

(Hmm: o seguinte é agora um pouco épico ...)

O design do diretório em sistemas de arquivos unix (que, para ser pedantes, são normalmente mas não necessariamente conectados a sistemas operacionais unix) representa uma visão maravilhosa, que na verdade reduz o número de casos especiais necessários.

Um 'diretório' é realmente apenas um arquivo no sistema de arquivos. Todo o conteúdo real dos arquivos no sistema de arquivos está em inodes (da sua pergunta, eu posso ver que você já está ciente de algumas dessas coisas). Não há estrutura para os inodes no disco - eles são apenas um monte de blocos de bytes numerados, espalhados como manteiga de amendoim no disco. Isso não é útil e, na verdade, é repelente para qualquer um que tenha um mínimo de mente arrumada.

O inode especial somente é o inode número 2 (não 0 ou 1, por razões de Tradição); inode 2 é um arquivo de diretório: o diretório raiz . Quando o sistema monta o sistema de arquivos, ele 'sabe' que deve ler o inode 2, para iniciar-se.

Um arquivo de diretório é apenas um arquivo, com uma estrutura interna que deve ser lida por opendir (3) e amigos. Você pode ver sua estrutura interna documentada em dir (5) (dependendo do seu sistema operacional); Se você olhar para isso, verá que a entrada do arquivo de diretório não contém quase nenhuma informação sobre o arquivo - isso é tudo no arquivo inode. Uma das poucas coisas que é especial sobre este arquivo é que a função open (2) receberá um erro se você tentar abrir um arquivo de diretório com um modo que permita a gravação. Vários outros comandos (para escolher apenas um exemplo, hexdump ) se recusarão a agir da maneira normal com arquivos de diretório, só porque provavelmente não é o que você quer fazer (mas esse é o caso especial deles, não o sistema de arquivos). p>

Um hard link é nada mais nem menos que uma entrada no mapa de um arquivo de diretório. Você pode ter duas (ou mais) entradas em tal mapa, que mapeiam para o mesmo número de inode: esse inode, portanto, tem dois (ou mais) hard links. Isso também explica porque o arquivo every tem pelo menos um 'hard link'. O inode tem uma contagem de referência, que registra quantas vezes esse inode é mencionado em um arquivo de diretório em algum lugar no sistema de arquivos (esse é o número que você vê quando faz ls -l ).

OK: estamos chegando ao ponto agora.

O arquivo de diretório é um mapa de strings ('nomes de arquivos') para números (números de inode). Esses números de inode são os números dos inodes dos arquivos que estão 'in' nesse diretório. Os arquivos que estão "in" nesse diretório podem incluir outros arquivos de diretório, portanto, seus números de inode estarão entre os listados no diretório. Portanto, se você tiver um arquivo /tmp/foo/bar , o arquivo de diretório foo incluirá uma entrada para bar , mapeando essa cadeia para o inode desse arquivo. Há também uma entrada no arquivo de diretório /tmp , para o arquivo de diretório foo , que é 'in' no diretório /tmp .

Quando você cria um diretório com mkdir (2), essa função

  1. cria um arquivo de diretório (com algum número de inode) com a estrutura interna correta,
  2. adiciona uma entrada ao diretório pai, mapeando o nome do novo diretório para este novo inode (que é responsável por um dos links),
  3. adiciona uma entrada ao novo diretório, mapeando a string '.' para o mesmo inode (isso responde pelo outro link), e
  4. adiciona outra entrada ao novo diretório, mapeando a string '..' para o inode do arquivo de diretório que ele modificou na etapa (2) (isso representa o maior número de links físicos que você verá nos arquivos de diretório que contêm subdiretórios).

O resultado final é que (quase) os únicos casos especiais são:

  • A função open (2) tenta dificultar o disparo no pé, impedindo a abertura de arquivos de diretório para gravação.
  • A função mkdir (2) facilita e simplifica as coisas adicionando algumas entradas extras ('.' e '..') ao novo arquivo de diretório, apenas para facilitar a movimentação pelo sistema de arquivos. Eu suspeito que o sistema de arquivos funcionaria perfeitamente sem '.' e '..', mas seria uma dor para usar.
  • O arquivo de diretório é um dos poucos tipos de arquivos marcados como 'especiais' - isso é o que realmente diz a coisas como o open (2) para se comportar de maneira um pouco diferente. Veja st_mode no stat (2).

(copiado da questão original do stackoverflow, 2011-10-20)

    
por 20.10.2011 / 10:29