Além das respostas de @ RuiFRibeiro e @ BruceEdiger, a distinção que você faz não é exatamente a distinção que o kernel faz. Na verdade, você tem vários tipos de arquivos: arquivos regulares, diretórios, links simbólicos, dispositivos, soquetes (e eu sempre esqueço alguns, para não tentar fazer uma lista completa). Você pode ter as informações sobre o tipo de arquivo ls
: é o primeiro caractere na linha. Por exemplo:
$ls -la /dev/sda
brw-rw---- 1 root disk 8, 0 17 nov. 08:29 /dev/sda
O 'b' no início indica que esse arquivo é um dispositivo de bloco. Um traço, significa um arquivo regular, 'l' um link simbólico e assim por diante. Essas informações são armazenadas nos metadados do arquivo e são acessíveis através da chamada do sistema, stat
por exemplo, para que o kernel possa ler de maneira diferente um arquivo e um link simbólico, por exemplo.
Em seguida, você faz outra distinção entre "arquivos reais" /bin/bash
e "arquivos virtuais", /proc/cpuinfo
mas ls
informa ambos como arquivos regulares, portanto a diferença é de outro tipo:
ls -la /proc/cpuinfo /bin/bash
-rwxr-xr-x 1 root root 829792 24 août 10:58 /bin/bash
-r--r--r-- 1 root wheel 0 20 nov. 16:50 /proc/cpuinfo
O que acontece é que eles pertencem a diferentes sistemas de arquivos. /proc
é o ponto de montagem de um pseudo-sistema de arquivos procfs
enquanto /bin/bash
em um sistema de arquivos em disco comum. Quando o Linux abre um arquivo (de maneira diferente dependendo do sistema de arquivos), ele preenche uma estrutura de dados file
que possui, entre outros atributos, uma estrutura de vários indicadores de função que descrevem como usar esse arquivo. Portanto, ele pode implementar comportamentos distintos para diferentes tipos de arquivos.
Por exemplo, estas são as operações anunciadas por /proc/meminfo
:
static int meminfo_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, meminfo_proc_show, NULL);
}
static const struct file_operations meminfo_proc_fops = {
.open = meminfo_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
Se você observar a definição de meminfo_proc_open
, poderá ver que essa função preenche um buffer na memória com as informações retornadas pela função meminfo_proc_show
, cuja tarefa é coletar dados sobre o uso da memória. Esta informação pode ser lida normalmente. Sempre que você abre o arquivo, a função meminfo_proc_open
é chamada e as informações sobre a memória são atualizadas.