Debian GNU/Hurd
Tradutores
Conceito
Antes de examinarmos os tradutores, consideremos os sistemas de arquivos regulares. Um sistema de arquivo é um armazenamento para uma árvore hierárquica de diretórios e arquivos. Você acessa os diretórios e os arquivos através de uma string de caracteres especial, o caminho (path, em inglês). Além disso, existem links simbólicos para referenciar um arquivo em diversos lugares na árvore, existem hard links para dar diversos nomes a um mesmo e único arquivo. Existem também arquivos de dispositivo especiais para comunicação com os drivers de dispositivos de hardware do kernel, e existem pontos de montagem para incluir outros armazenamentos na árvore de diretórios. E existem objetos obscuros como os FIFOs.
Embora esses objetos sejam muito diferentes, eles compartilham de algumas propriedades comuns, por exemplo, todos eles têm um(a) proprietário(a) e um grupo associados, como também direitos de acesso (permissões). Esta informação fica escrita em inodes. Isto é, na verdade, uma convergência adicional: todo objeto tem exatamente um inode associado a ele (hard links são algo de especial já que eles compartilham um mesmo e único inode). Às vezes, o inode tem informações adicionais armazenadas nele. Por exemplo, o inode pode conter o alvo de um link simbólico.
Contudo, esses aspectos comuns geralmente não são aproveitados nas
implementações, apesar da interface comum de programação entre eles. Todos os
inodes podem ser acessados através de chamadas POSIX padrões, por exemplo,
read()
e write()
. Ou para adicionar um
novo tipo de objeto (por exemplo, um novo tipo de link) para um kernel unix
comum e monolítico, você precisaria modificar o código para cada sistema
de arquivos separadamente.
No Hurd, as coisas funcionam diferentemente. Embora no Hurd um servidor especial de sistema de arquivos possa explorar propriedades especiais de tipos de objeto padrões, como os links (no sistema de arquivo ext2 com links rápidos, por exemplo), ele tem uma interface genérica para adicionar tais funcionalidades sem modificar o código existente.
O truque está em permitir a um programa que se insira entre o atual conteúdo de um arquivo e o(a) usuário(a) que está acessando este arquivo. Tal programa é chamado de tradutor, porque ele é capaz de processar requisições de entrada por muitas e diferentes maneiras. Em outras palavras, um tradutor é um servidor Hurd que fornece uma interface básica de sistema de arquivos.
Os tradutores têm propriedades muito interessantes. Do ponto de vista do kernel, eles são apenas outro processo de usuário(a). Isto é, os tradutores podem ser executados por quaisquer usuários(as). Você não precisa de privilégios de root para instalar ou para modificar um tradutor, você somente precisa dos direitos de acesso para o inode subjacente ao tradutor ao qual está anexado. Muitos tradutores não requerem um arquivo real para operar, eles podem fornecer informações por seus próprios meios. Este é o motivo da informação sobre tradutores ficar armazenada no inode.
Os tradutores são responsáveis por servir todas as operações de sistema
de arquivo que envolvem o inode no qual estão anexados. Porque não estão
restritos aos usuais conjuntos de objetos (arquivo de dispositivo, link, etc.),
eles estão livres para retornar qualquer coisa que faça sentido ao(à)
programador(a). Pode-se imaginar um tradutor que se comporta como um
diretório quando acessado por cd
ou ls
e, ao
mesmo tempo, se comporta como um arquivo quando acessado por
cat
.
Exemplos
Pontos de montagem
Um ponto de montagem pode ser visto como um inode que tem um tradutor especial anexado a ele. Seu propósito seria traduzir as operações do sistema de arquivos no ponto de montagem em operações de sistema de arquivos em outro armazenamento, por exemplo, em uma outra partição.
De fato, é assim que os sistemas de arquivos são implementados sob o Hurd. Um sistema de arquivos é um tradutor. Este tradutor pega um armazenamento como seu argumento e é capaz de servir todas as operações de sistema de arquivos transparentemente.
Arquivos de dispositivo
Existem muitos e diferentes arquivos de dispositivos, e em sistemas de kernel monolítico, eles são todos fornecidos pelo kernel mesmo. No Hurd, todos os arquivos de dispositivo são fornecidos por tradutores. Um tradutor pode fornecer suporte para vários arquivos de dispositivo similares, por exemplo, todas as partições do disco rígido. Deste modo, o número de tradutores realmente existentes é muito pequeno. Contudo, note que para cada arquivo de dispositivo acessado, uma tarefa de tradutor separada é iniciada. Porque o Hurd é profundamente multithread, isso sai muito barato.
Quando hardware é envolvido, um tradutor geralmente começa a se comunicar com
o kernel para obter os dados do hardware. Entretanto, se não é preciso acesso
ao hardware, o kernel não precisa estar envolvido. Por exemplo,
/dev/zero
não requer acesso ao hardware e, portanto, pode ser
implementado completamente no espaço de usuário(a).
Links simbólicos
Um link simbólico pode ser visto como um tradutor. Ao acessar o link simbólico, um tradutor seria iniciado, o qual encaminharia a requisição para o sistema de arquivos que contenha o arquivo para o qual o link aponta.
Contudo, para uma melhor performance, os sistemas de arquivos que possuem suporte nativo aos links simbólicos podem tirar vantagem desta funcionalidade e implementar links simbólicos de maneira diferente. Internamente, o acesso a um link simbólico não iniciaria um novo processo de tradutor. Porém, para o(a) usuário(a), ainda pareceria como se o tradutor passivo estivesse envolvido (veja abaixo uma explicação sobre o que é um tradutor passivo).
Devido ao Hurd vir com um tradutor de symlink, qualquer servidor de sistema de arquivos que fornece suporte para tradutores automaticamente tem suporte para symlinks (e firmlinks, e arquivos de dispositivos, etc.)! Ou seja, você pode conseguir um sistema de arquivos funcionando bem rápido e adicionar suporte nativo aos symlinks e a outras funcionalidades mais tarde.
Tradutores passivos, tradutores ativos
Existem dois tipos de tradutores, passivos e ativos. Eles realmente são coisas completamente diferentes, então não confunda; mas eles mantêm uma relação próxima.
Tradutores ativos
Um tradutor ativo é um processo de tradutor em execução, como visto acima.
Você pode definir e remover tradutores ativos usando o comando
settrans -a
.
A opção -a
é necessária para dizer ao
settrans
que você quer modificar o tradutor ativo.
O comando settrans
recebe três tipos de argumentos. Primeiro, você
pode definir opções para o comando settrans
mesmo, como
-a
para modificar o tradutor ativo. A seguir você define o inode
que quer modificar. Lembre-se que um tradutor está sempre associado com um
inode na hierarquia de diretórios. Você somente pode modificar um inode
por vez. Se você não especificar mais nenhum argumento, settrans
tentará remover um tradutor existente. O quanto ele vai tentar depende das
opções de imposição que você especificar (se o tradutor está em uso por
qualquer processo, você obterá uma mensagem de erro "device or resource busy"
- dispositivo ou recurso ocupado - a menos que você force a remoção).
Mas se você especificar argumentos adicionais, eles serão interpretados como
uma linha de comando para executar o tradutor. Isto é, o próximo argumento
é o nome de arquivo do executável do tradutor. Argumentos adicionais são
opções para o tradutor, e não para o comando settrans
.
Por exemplo, para montar uma partição ext2fs, você pode executar
settrans -a -c /mnt /hurd/ext2fs /dev/hd2s5
. A opção
-c
criará um ponto de montagem se ele ainda não
existir. Aliás, não precisa ser um diretório. Para desmontar, você tentaria
settrans -a /mnt
.
Tradutores passivos
Um tradutor passivo é definido e modificado pela mesma sintaxe dos tradutores
ativos (somente ignore a opção -a
), então tudo o que foi dito
acima também é verdade para os tradutores passivos. Contudo, existe uma
diferença: tradutores passivos ainda não foram iniciados.
Isto faz sentido porque isto é o que você geralmente quer. Você não quer a partição montada a menos que você realmente acesse os arquivos nesta partição. Você não quer ligar a rede a menos que exista algum tráfego, e assim por diante.
Ao contrário, a primeira vez que um tradutor passivo é acessado, ele é automaticamente lido do inode e um tradutor ativo é iniciado a partir dele usando a linha de comando que foi armazenada no inode. Isto é similar à funcionalidade de montagem automática do Linux. Contudo, ele não vem como um bônus que você tem que configurar manualmente, mas como uma parte integral do sistema. Assim, definir tradutores passivos posterga o início da tarefa de tradutor até que você realmente precise dela. A propósito, se o tradutor ativo morre por alguma razão, a próxima vez em que o inode for acessado, o tradutor é reiniciado.
Existe uma outra diferença: tradutores ativos podem morrer ou se perder.
Logo após o término do processo do tradutor ativo (por exemplo, porque você
reiniciou a máquina), ele estará perdido para sempre. Tradutores passivos não
são transientes e ficam no inode durante a reinicialização até que você
modifique-os com o programa settrans
ou apague os inodes aos
quais estão anexados. Isto significa que você não precisa manter um
arquivo de configuração com seus pontos de montagem.
Um último ponto: mesmo se você definiu um tradutor passivo, você ainda pode definir um tradutor ativo diferente. Somente se o tradutor é automaticamente iniciado porque não existia tradutor ativo quando o inode foi acessado, assim o tradutor passivo é considerado.
Gerenciando tradutores
Como mencionado acima, você pode usar
settrans
para definir e alterar tradutores passivos e ativos. Existem muitas opções
para alterar o comportamento do settrans
no caso de algo dar
errado e para condicionar suas ações. Aqui estão alguns usos comuns:
settrans -c /mnt /hurd/ext2fs /dev/hd2s5
monta uma partição, o tradutor permanece após a reinicialização.settrans -a /mnt /hurd/ext2fs ~/dummy.fs
monta um sistema de arquivos dentro de um arquivo de dados, o tradutor some se ele morrer.settrans -fg /nfs-data
força um tradutor a sumir.
Você pode usar o comando
showtrans
para ver se um tradutor está anexado a um inode. Porém, isso só vai mostrar
o tradutor passivo.
Você pode alterar as opções de um tradutor ativo (de sistema de arquivos) com
fsysopts
sem realmente reiniciá-lo. Isto é muito
conveniente. Por exemplo, você pode fazer o chamado "remontando uma
partição somente-leitura" sob o Linux executando simplesmente fsysopts
/mntpoint --readonly
. O tradutor ativo em execução
mudará seu comportamento de acordo com sua requisição, se possível. O
fsysopts /mntpoint
sem nenhum parâmetro mostra as configurações
atuais.
Exemplos
Eu recomendo que você inicie pela leitura do comando /bin/mount
,
é só um pequeno script. Devido à configuração de tradutores de sistemas de
arquivos ser similar à montagem de partições, você facilmente pode captar
o conceito desta maneira. Crie uma imagem de sistema de arquivo com
dd if=/dev/zero of=dummy.fs bs=1024k
count=8; mke2fs dummy.fs
e "monte-a" com settrans -c dummy
/hurd/ext2fs `pwd`/dummy.fs
. Note que o tradutor ainda não
iniciou, nenhum novo processo ext2fs
está executando (verifique
com ps Aux
). Verifique se tudo está correto usando
showtrans
.
Agora digite ls dummy
e você perceberá um curto atraso que
acontece enquanto o tradutor é iniciado. Após isso, não haverá mais atrasos
acessando o dummy. Sob o Linux, poderia se dizer que você montou automaticamente
um sistema de arquivo em loop. Verifique com ps Aux
que agora
existe um processo ext2fs dummy
ativo e executando. Agora
coloque alguns arquivos no novo diretório. Tente fazer o sistema de arquivos
ficar em somente-leitura com fsysopts
.
Note quão longe vão as falhas das tentativas de escrita. Tente matar o
tradutor ativo com settrans -g
.
Agora você deve ter alguma compreensão do que está acontecendo. Lembre-se
de que foi somente um servidor especial, o servidor ext2fs do Hurd.
Existem muitos mais servidores no diretório hurd
. Alguns deles
são para sistemas de arquivos. Alguns são necessários para funcionalidades
de sistemas de arquivo, como os links. Alguns são necessários para arquivos
de dispositivos. Alguns são úteis para redes. Imagine "montar" um servidor
FTP com settrans
e baixar arquivos
simplesmente com o comando padrão cp
. Ou editar seus sites web
com emacs /ftp/homepage.my.server.org/index.html
!