Por que eu posso gato / dev?

41

Eu posso cat /dev, posso ls /dev, não posso less /dev. Por catque me permite catesse diretório, mas não outros diretórios?

Imagem deste comportamento no zsh.

haboutnnah
fonte
@KamilMaciorowski, aqui está a saída e neofetchpara sua informação :) i.imgur.com/3azpnDt.png
haboutnnah

Respostas:

43

Historicamente (até V7 UNIX ou por volta de 1979), a readchamada do sistema funcionava em arquivos e diretórios. readem um diretório retornaria uma estrutura de dados simples que um programa do usuário analisaria para obter as entradas do diretório. De fato, a lsferramenta V7 fez exatamente isso - readem um diretório, analise a estrutura de dados resultante e produza em um formato de lista estruturada.

À medida que os sistemas de arquivos ficaram mais complexos, essa estrutura de dados "simples" ficou mais complicada, a ponto de uma readdirfunção de biblioteca ser adicionada para ajudar os programas a analisar a saída de read(directory). Sistemas e sistemas de arquivos diferentes podem ter diferentes formatos no disco, o que estava ficando complicado.

Quando a Sun apresentou o NFS (Network File System), eles queriam abstrair completamente a estrutura de diretórios em disco. Em vez de fazer do read(directory)retorno uma representação independente da plataforma do diretório, eles adicionaram uma nova chamada do sistema - getdirents- e foram banidos readem diretórios montados na rede. Essa chamada do sistema foi rapidamente adaptada para funcionar em todos os diretórios em vários tipos de UNIX, tornando-o o caminho padrão para obter o conteúdo dos diretórios. (Histórico abstraído de https://utcc.utoronto.ca/~cks/space/blog/unix/ReaddirHistory )

Como readdiragora é a maneira padrão de ler diretórios, read(directory)geralmente não é implementado (retornando -EISDIR) na maioria dos sistemas operacionais modernos (QNX, por exemplo, é uma exceção notável que é implementada readdircomo read(directory)). No entanto, com o design do "sistema de arquivos virtual" na maioria dos kernels modernos, na verdade cabe ao sistema de arquivos individual se a leitura de um diretório funciona ou não.

E, de fato, no macOS, o devfssistema de arquivos subjacente ao /devponto de montagem realmente suporta a leitura ( https://github.com/apple/darwin-xnu/blob/xnu-4570.1.46/bsd/miscfs/devfs/devfs_vnops.c#L629 ) :

static int
devfs_read(struct vnop_read_args *ap)
{
        devnode_t * dn_p = VTODN(ap->a_vp);

    switch (ap->a_vp->v_type) {
      case VDIR: {
          dn_p->dn_access = 1;

          return VNOP_READDIR(ap->a_vp, ap->a_uio, 0, NULL, NULL, ap->a_context);

Isso chama explicitamente READDIRse você tentar ler /dev(a leitura de arquivos sob /devé tratada por uma função separada - devfsspec_read). Portanto, se um programa chamar a chamada do readsistema /dev, terá êxito e obterá uma lista de diretórios!

Este é efetivamente um recurso que permanece sob os primórdios do UNIX e que não é abordado há muito tempo. Parte de mim suspeita que isso esteja sendo mantido por algum motivo de compatibilidade com versões anteriores, mas poderia ser tão facilmente o fato de que ninguém se importa o suficiente para remover o recurso, pois não está prejudicando nada.

nneonneo
fonte
Provavelmente o último, visto que foi removido da maioria dos diretórios.
precisa saber é o seguinte
36

Menos é um visualizador de arquivos de texto, cat é uma ferramenta para copiar dados arbitrários. Portanto, menos realiza sua própria verificação para garantir que você não esteja abrindo algo que terá grandes quantidades de dados ou se comportará de maneira muito estranha. Por outro lado, o gato não tem tal verificação - se o kernel permite abrir algo (mesmo que seja um tubo ou um dispositivo ou algo pior), o gato irá lê-lo.

Então, por que o sistema operacional permite que o gato abra diretórios? Tradicionalmente, em sistemas no estilo BSD, todos os diretórios podiam ser lidos como arquivos, e era assim que os programas listavam um diretório em primeiro lugar: apenas interpretando as estruturas dirent armazenadas no disco.

Posteriormente, essas estruturas em disco começaram a divergir da diretiva usada pelo kernel: onde anteriormente um diretório era uma lista linear, os sistemas de arquivos posteriores começaram a usar hashtables, árvores B e assim por diante. Portanto, ler diretórios diretamente não era mais simples - o kernel desenvolveu funções dedicadas para isso. (Não tenho certeza se esse foi o motivo principal ou se foram adicionados principalmente por outros motivos, como cache.)

Alguns sistemas BSD continuam permitindo abrir todos os diretórios para leitura; Não sei se eles fornecem os dados brutos do disco, ou se eles retornam uma lista de diretórios emulados ou se permitem que o driver do sistema de arquivos decida.

Portanto, talvez o macOS seja um desses sistemas operacionais em que o kernel permite, desde que o sistema de arquivos forneça os dados. E a diferença é que /devestá em um devfssistema de arquivos que foi escrito para permitir isso nos primeiros dias, enquanto /em um sistema de arquivos APFS que omitiu esse recurso por ser desnecessário nos tempos modernos.

Disclaimer: Na verdade, eu não fiz nenhuma pesquisa sobre BSDs ou macOS. Eu estou apenas voando.

gravidade
fonte
Isso parece fazer sentido. Existem outras seções de armazenamento que diferem do sistema de arquivos padrão do SO? Eu assumi que /etcsim, então usei isso como minha referência.
Haboutnnah 2/11
2
Pelo contrário, geralmente / etc é apenas uma pasta comum que contém arquivos regulares. Porém, pode haver outros sistemas de arquivos virtuais - execute mountou /sbin/mountpara ver o que está montado no momento.
grawity
Você está certo! Veja isto: i.imgur.com/pcVpo1o.png
haboutnnah
Isso é realmente puro @grawity, i.imgur.com/8QuR0FK.png
haboutnnah
6
@haboutnnah Sua captura de tela confirma que /devé um sistema de arquivos virtual usando o devfsdriver, enquanto /etcfaz parte do /sistema de arquivos usando o apfsdriver. Portanto, a razão catvai ler um e não o outro é a diferença entre o apfse devfsmotoristas.
kasperd