Existem arquivos especiais no Linux que não são realmente arquivos.
Os exemplos mais notáveis e claros disso estão na dev
pasta "arquivos", como:
/dev/null
- Ignora qualquer coisa que você escreve no arquivo/dev/random
- Envia dados aleatórios em vez do conteúdo de um arquivo/dev/tcp
- Envia todos os dados que você escreve para esse arquivo pela rede
Primeiro de tudo, qual é o nome desses tipos de "arquivos" que são realmente algum tipo de script ou binário disfarçado?
Segundo, como eles são criados? Esses arquivos estão embutidos no sistema no nível do kernel ou existe uma maneira de você mesmo criar um "arquivo mágico" (que tal um /dev/rickroll
)?
man 2 mknod
open()
,read()
,close()
, etc. Depois disso, cabe ao softwareRespostas:
/dev/zero
é um exemplo de um "arquivo especial" - particularmente, um "nó do dispositivo". Normalmente, eles são criados pelo processo de instalação da distribuição, mas você pode criá-los totalmente, se quiser.Se você perguntar
ls
sobre/dev/zero
:O "c" no início informa que esse é um "dispositivo de caractere"; o outro tipo é "dispositivo de bloco" (impresso
ls
como "b"). Muito grosso modo, dispositivos de acesso aleatório, como discos rígidos, tendem a ser dispositivos de bloco, enquanto coisas seqüenciais, como unidades de fita ou placa de som, tendem a ser dispositivos de caracteres.A parte "1, 5" é o "número principal do dispositivo" e o "número menor do dispositivo".
Com essas informações, podemos usar o
mknod
comando para criar nosso próprio nó de dispositivo:Isso cria um novo arquivo chamado
foobar
, na pasta atual, que faz exatamente a mesma coisa que/dev/zero
. (É claro que você pode definir permissões diferentes, se quiser.) Todo esse "arquivo" realmente contém os três itens acima - tipo de dispositivo, número principal, número menor. Você pode usarls
para procurar os códigos de outros dispositivos e recriá-los também. Quando você se cansar, userm
para remover os nós do dispositivo que você acabou de criar.Basicamente, o número principal informa ao kernel do Linux com qual driver de dispositivo conversar e o número menor informa ao driver de dispositivo de que dispositivo você está falando. (Por exemplo, você provavelmente tem um controlador SATA, mas talvez vários discos rígidos estejam conectados a ele.)
Se você deseja inventar novos dispositivos que fazem algo novo ... bem, precisará editar o código-fonte do kernel do Linux e compilar seu próprio kernel personalizado. Então não vamos fazer isso! :-) Mas você pode adicionar arquivos de dispositivos que duplicam os que você já possui. Um sistema automatizado como o udev está basicamente apenas observando eventos do dispositivo e chamando
mknod
/rm
para você automaticamente. Nada mais mágico que isso.Ainda existem outros tipos de arquivos especiais:
O Linux considera um diretório um tipo especial de arquivo. (Normalmente, você não pode abrir um diretório diretamente, mas, se pudesse, descobriria que é um arquivo normal que contém dados em um formato especial e informa ao kernel onde encontrar todos os arquivos nesse diretório.)
Um link simbólico é um arquivo especial. (Mas um link físico não é.) Você pode criar links simbólicos usando o
ln -s
comando (Procure a página de manual para isso.)Há também uma coisa chamada "pipe nomeado" ou "FIFO" (fila de entrada e saída). Você pode criar um com
mkfifo
. Um FIFO é um arquivo mágico que pode ser aberto por dois programas ao mesmo tempo - uma leitura e uma escrita. Quando isso acontece, funciona como um tubo de concha normal. Mas você pode iniciar cada programa separadamente ...Um arquivo que não é "especial" de forma alguma é chamado de "arquivo regular". Você ocasionalmente verá menção disso na documentação do Unix. É isso que significa; um arquivo que não é um nó de dispositivo ou um link simbólico ou qualquer outra coisa. Apenas um arquivo normal todos os dias sem propriedades mágicas.
fonte
mknod
, corracat /proc/devices
para ver os números principais de todos os drivers. O que nos leva a outro tipo de arquivo especial do/proc
sistema de arquivos ( esta resposta fala sobre isso).A maioria das
/dev
entradas são inodes de dispositivo de bloco ou de dispositivo de caracteres. A Wikipedia tem muitos detalhes sobre isso, que não vou repetir.Mas o
/dev/tcp
que é mencionado na sua pergunta não é explicado por nenhuma das respostas existentes./dev/tcp
e/dev/udp
são diferentes da maioria das outras/dev
entradas. Os dispositivos de bloco e de caracteres são implementados pelo kernel, mas/dev/tcp
e/dev/udp
são implementados em modo de usuário.O shell bash é um programa que possui uma implementação
/dev/tcp
e/dev/udp
(copiado deksh93
). Quando você tenta abrir um caminho abaixo daqueles com operadores de redirecionamento de bash, ele não executa umaopen
chamada de sistema comum . Em vez disso, o bash criará um soquete TCP e o conectará à porta especificada.Isso é implementado no modo de usuário e apenas em alguns programas, como pode ser visto no exemplo a seguir, que demonstra a diferença entre permitir
bash
ecat
tentar abrir/dev/tcp/::1/22
A diferença
ksh93
é quebash
isso só fará essas conexões TCP com operadores de redirecionamento, e não nos outros lugares em que ele pode abrir arquivos como osource
ou.
embutido.fonte
gawk
casos semelhantes da mesma forma/inet{,4,6}/{tcp,udp}/$port/$remote/$rport
, desde algo em torno de 2010 (não me lembro exatamente e não consigo encontrar notas de versão)./dev/tcp
é que NÃO é um arquivo. Nunca existe um arquivo chamado isso. A sintaxe de Bash para abrir soquetes usa a string/dev/tcp/address
como um nome de arquivo, mas chamá-la de "arquivo implementado no espaço do usuário" parece estranha. Interessante queksh
conecta esses nomes de arquivos a tudo, não apenas redireciona. Isso está mais perto de "implementar um arquivo".bash
apenas copiou esse comportamento, mas ele se origina em outro lugar.Além dos nós do dispositivo explicados em outras respostas (criadas com o mknod (2) ou fornecidas por alguns devfs ), o Linux possui outros arquivos "mágicos" fornecidos por sistemas de arquivos virtuais especiais , especialmente em
/proc/
(consulte proc (5) , leia sobre procfs ) e em/sys/
(leia sobre sysfs ).Esses pseudo arquivos (que aparecem -eg para stat (2) - como arquivos comuns, não como dispositivos) são uma visão virtual fornecida pelo kernel; em particular, a leitura de
/proc/
(por exemplo, comcat /proc/$$/maps
ou por open (2) ing/proc/self/status
em seu programa), geralmente não envolvem qualquer física I / O de disco ou rede, para que é bastante rápido.Para criar algum pseudo-arquivo adicional em
/proc/
geral, você deve escrever seu próprio módulo do kernel e carregá-lo (veja, por exemplo, isto ).fonte
Eles são chamados nós de dispositivos e são criados manualmente com
mknod
ou automaticamente porudev
. Eles são tipicamente interfaces semelhantes a arquivos para caracteres ou dispositivos de bloco com drivers no kernel - por exemplo, discos são dispositivos de bloco, ttys e portas seriais etc. são dispositivos de caracteres.Também existem outros tipos de arquivos "especiais", incluindo pipes nomeados, fifos e soquetes.
fonte
Como outros usuários já explicaram detalhadamente, arquivos especiais requerem código para fazer backup deles. No entanto, ninguém parece ter mencionado que o Linux fornece várias maneiras de escrever esse código no espaço do usuário:
R. O FUSE (sistema de arquivos no USErspace) permite escrever algo como
/proc
sem risco de travar o kernel e fazê-lo em um idioma / tempo de execução de sua escolha, como Go , Node.js , Perl , PHP , Python , Ruby , Rust , etc .Ele também tem a vantagem de que os sistemas de arquivos FUSE podem ser montados sem
sudo
porque são executados como o usuário que está montando.Aqui estão alguns exemplos de coisas que as pessoas escreveram usando o FUSE:
B. Se você deseja criar um dispositivo de entrada virtual como teclado, mouse, joystick, etc. (por exemplo, para escrever um driver do espaço do usuário para um dispositivo USB com o qual você está falando
libusb
), há entrada .As ligações para isso são mais difíceis de encontrar, mas eu sei que elas existem para Go (somente teclado), Python e Ruby (2) .
Exemplos de uso de entrada do mundo real incluem:
C. Para dispositivos de caracteres genéricos, há CUSE (dispositivos de caracteres no USErspace). É muito menos popular.
O único usuário da API CUSE que estou pessoalmente ciente é o mesmo programa que levou a sua criação: osspd , que implementa
/dev/dsp
,/dev/adsp
e/dev/mixer
(a API de áudio OSS) no espaço do usuário para que possam ser encaminhados através PulseAudio ou dmix.A única ligação CUSE que consegui encontrar é cusepy , que não é atualizada desde 2010.
D. Você pode não precisar de um novo arquivo especial.
Por exemplo, você pode abrir a comunicação bruta com qualquer dispositivo USB usando libusb (Lista de ligações na página) e depois se comunicar com outros programas através de algum outro mecanismo (soquetes TCP / UDP, leitura / gravação de stdin / stdout ou arquivos regulares no disco etc.).
fonte
poll
, mas como o cusepy usa ctypes e as ligações são geradas automaticamente com base nos arquivos de cabeçalho C, corrigir todas as funções ausentes é apenas uma questão de adicionar o nome da função desejada à lista de funções exportadas nosetup.py
.O livro Linux Device Drivers (altamente recomendado) explica isso em detalhes, e você ainda cria um módulo do kernel que faz isso como exemplo, mas, em poucas palavras, cada driver de dispositivo tem funções específicas que são chamadas quando um arquivo é aberto, fechado , leia, escreva etc. Os arquivos "especiais" fazem algo especial nessas funções, em vez de acessar o hardware de armazenamento em um disco.
Por exemplo, a função de gravação
/dev/null
simplesmente não faz nada, ignorando os bytes. A função de leitura para/dev/random
retorna um número aleatório.fonte
mount -t devtmpfs
Também é interessante ver que, em sistemas modernos,
/dev
normalmente é do tipo de sistema de arquivos que pode ser montado onde você quiser. Ubuntu 16.04:Isso é ativado
CONFIG_DEVTMPFS=y
e permite que o próprio kernel crie e destrua arquivos de dispositivo, conforme necessário.CONFIG_DEVTMPFS_MOUNT=y
Esta opção ativa o devtmpfs de montagem automática do kernel
/dev
.drivers/base/Kconfig
documentos:file_operations
Por fim, você deve criar seu próprio módulo do kernel do dispositivo de caracteres para ver exatamente o que está acontecendo.
Aqui está um exemplo mínimo executável: Noções básicas sobre arquivos de dispositivo de caractere (ou caractere especial)
O passo mais importante é configurar a
file_operations
estrutura, por exemplo:que contém ponteiros de função que são chamados para cada chamada do sistema relacionada a arquivos.
Torna-se óbvio que você substitui as chamadas de sistema relacionadas a arquivos para fazer o que quiser, e é assim que o kernel implementa dispositivos como esse
/dev/zero
.Crie
/dev
entradas automaticamente semmknod
O mistério final é como o kernel cria
/dev
entradas automaticamente .O mecanismo pode ser observado criando um módulo do kernel que faz isso sozinho, como mostrado em: https://stackoverflow.com/questions/5970595/how-to-create-a-device-node-from-the-init-module- code-of-a-linux-kernel-module / 45531867 # 45531867 e se resume a uma
device_create
chamada.fonte