Eu posso cat /dev
, posso ls /dev
, não posso less /dev
. Por cat
que me permite cat
esse diretório, mas não outros diretórios?
Eu posso cat /dev
, posso ls /dev
, não posso less /dev
. Por cat
que me permite cat
esse diretório, mas não outros diretórios?
Respostas:
Historicamente (até V7 UNIX ou por volta de 1979), a read
chamada do sistema funcionava em arquivos e diretórios. read
em 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 ls
ferramenta V7 fez exatamente isso - read
em 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 readdir
funçã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 read
em 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 readdir
agora é 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 readdir
como 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 devfs
sistema de arquivos subjacente ao /dev
ponto 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 READDIR
se 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 read
sistema /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.
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 /dev
está em um devfs
sistema 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.
/etc
sim, então usei isso como minha referência.
mount
ou /sbin/mount
para ver o que está montado no momento.
/dev
é um sistema de arquivos virtual usando o devfs
driver, enquanto /etc
faz parte do /
sistema de arquivos usando o apfs
driver. Portanto, a razão cat
vai ler um e não o outro é a diferença entre o apfs
e devfs
motoristas.
neofetch
para sua informação :) i.imgur.com/3azpnDt.png