Existem basicamente dois tipos diferentes de coisas aqui:
- Sistemas de arquivos normais, que armazenam arquivos em diretórios com dados e metadados, de maneira familiar (incluindo links, links físicos e assim por diante). Estes são frequentemente, mas não sempre, suportados por um dispositivo de bloco para armazenamento persistente (um tmpfs vive apenas na RAM, mas é de outra forma idêntico a um sistema de arquivos normal). A semântica destes é familiar; ler, escrever, renomear e assim por diante, tudo funciona da maneira que você espera.
- Sistemas de arquivos virtuais, de vários tipos.
/proc
e/sys
são exemplos aqui, assim como sistemas de arquivos customizados do FUSE comosshfs
ouifuse
. Há muito mais diversidade neles, porque na verdade eles apenas se referem a um sistema de arquivos com semânticas que são de alguma forma 'customizadas'. Assim, quando você lê a partir de um arquivo em/proc
, você não está realmente acessando uma parte específica de dados que foi armazenada por outra coisa escrita anteriormente, como em um sistema de arquivos normal. Você está basicamente fazendo uma chamada de kernel, solicitando algumas informações geradas on-the-fly. E esse código pode fazer o que quiser, já que é apenas alguma função que implementaread
semântica. Assim, você tem o comportamento estranho dos arquivos em/proc
, como por exemplo, fingir ser symlinks quando eles não são realmente.
A chave é que /dev
é, na verdade, um dos primeiros tipos. É normal nas distribuições modernas ter /dev
algo como um tmpfs, mas em sistemas mais antigos, era normal que fosse um diretório simples no disco, sem nenhum atributo especial. A chave é que os arquivos em /dev
são nós de dispositivo, um tipo de arquivo especial semelhante a FIFOs ou soquetes Unix; um nó de dispositivo tem um número maior e menor, e ler ou gravá-los é fazer uma chamada para um driver de kernel, da mesma forma que ler ou escrever um FIFO está chamando o kernel para armazenar em buffer sua saída em um pipe. Este driver pode fazer o que quiser, mas geralmente toca hardware de alguma forma, por ex. para acessar um disco rígido ou reproduzir som nos alto-falantes.
Para responder às perguntas originais:
-
Existem duas questões relevantes para saber se o 'arquivo existe' ou não; Estes são se o arquivo do nó do dispositivo literalmente existe, e se o código do kernel é significativo. O primeiro é resolvido como qualquer coisa em um sistema de arquivos normal. Sistemas modernos usam
udev
ou algo parecido para assistir a eventos de hardware e automaticamente criar e destruir os nós de dispositivos sob/dev
de acordo. Mas sistemas mais antigos, ou construções customizadas leves, podem ter todos os seus nós de dispositivo literalmente no disco, criados antes do tempo. Enquanto isso, quando você lê esses arquivos, você está fazendo uma chamada para o código do kernel que é determinado pelos números maiores e menores do dispositivo; Se isso não for razoável (por exemplo, você está tentando ler um dispositivo de bloco que não existe), você só receberá algum tipo de erro de E / S. -
A maneira como funciona o código do kernel a ser chamado para qual arquivo de dispositivo varia. Para sistemas de arquivos virtuais como
/proc
, eles implementam suas próprias funçõesread
ewrite
; o kernel apenas chama esse código dependendo de qual ponto de montagem ele está, e a implementação do sistema de arquivos cuida do resto. Para arquivos de dispositivos, ele é enviado com base nos números principais e secundários do dispositivo.