Um sistema de arquivos virtual (abreviado como VFS, do inglês Virtual File System), é uma camada de abstração em cima de um sistema de arquivos mais concreto. O propósito de um VFS é permitir que as aplicações clientes tenham acesso a diversos tipos de sistemas de arquivos concretos de uma maneira uniforme.[1]
Introdução
O Virtual Filesystem (também conhecido como Virtual Filesystem Switch ou VFS) é uma camada de software do núcleo que trata de todas as chamadas de sistema relacionadas a um sistema de arquivos Unix. Sua principal vantagem é prover uma interface genérica para diversos tipos de sistemas de arquivos. Ou seja, VFS permite que chamadas de sistemas genéricas, tais como open( ) e read( ),possam ser executadas independentemente do sistema de arquivos usados ou do meio físico. Para o VFS e para o resto do Núcleo os Sistemas de Arquivos parecem iguais.
Por exemplo, vamos supor que um usuário entra com o seguinte comando no shell:
$ cp /floppy/TEST /tmp/test
Nesse caso, /floppy é o mount point de um diskette MS-DOS e /tmp é um diretório Second Extended Filesystem (Ext2) comum. O VFS é uma camada de abstração entre a aplicação e as implementações do sistema de arquivos. Portanto, o programa cp não precisa saber os tipos de arquivo do /floppy/TEST e do /tmp/test. Ao invés disso, o cp interage com o VFS usando chamadas de sistema comuns conhecidas por qualquer um que já programou em Unix.
Objetos do VFS
Por ser orientado a objetos e escrito em C, as estruturas de dados do VFS são simuladas nessa linguagem. O VFS foi construído para trabalhar com Sistemas de Arquivo que naturalmente implementam conceitos já na organização da informação no disco e define quatro objetos básicos. O Objeto INODE armazena informações gerais sobre um arquivo específico. Em sistemas de arquivo de disco, esse objeto geralmente corresponde a um bloco de controle de arquivo armazenado no disco. Cada objeto inode é associado a um número inode, que identifica de forma única o arquivo dentro do sistema de arquivos. O Objeto Superbloco armazena informações sobre um sistema de arquivos montado. Para um sistema de arquivos de disco, esse objeto geralmente corresponde ao bloco de controle do sistema de arquivos armazenado em disco. O Objeto Dentry, que armazena informações sobre a linkagem de um diretório (isso é, o nome do arquivo) com o arquivo correspondente. Cada sistema de arquivo armazena essa informação de uma forma única no disco. E por último, existe o Objeto File que armazena informações sobre a interação entre um arquivo aberto e um processo. Essa informação existe somente na memória do núcleo durante o período em que um processo tem um arquivo aberto.
Estrutura de Dados
Objeto Superbloco
Utilizado para armazenar informações sobre um sistema de arquivos específico. O Objeto Superbloco é representado pela estrutura super block a qual é instanciada pela função alloc_super(). Todos os objetos Superbloco estão ligados através de uma lista circular duplamente encadeada. O primeiro elemento dessa lista é representado pela variável do superbloco, enquanto o campo s_list do objeto superbloco guarda os ponteiros para o elemento adjacente na lista. O sb_lock protege a lista contra acesso concorrente em sistemas multiprocessados. O campo s_fs aponta para informações do Superbloco que pertencem a um sistema de arquivo específico, por exemplo, se um Objeto Superbloco se refere a um sistema de arquivos do tipo Ext2, o campo aponta para uma estrutura ext2_sb_info, a qual inclui a máscara de alocação no disco e outros dados irrelevantes para o modelo de arquivo comum do VFS.
Isso no entanto leva a um novo problema: o superbloco do VFS pode perder a sincronia com o superbloco correspondente no disco. Portanto, é necessário introduzir uma flag s_dirt, que indica que os dados no disco precisam ser atualizados. A falta de sincronia leva ao velho problema de sistemas de arquivo corrompidos quando o computador é desligado abruptamente, sem dar chance ao usuário de desligar o sistema com segurança.
Cada Sistema de Arquivos baseado em disco precisa acessar e atualizar os locais (endereços) para poder alocar e liberar os blocos no disco. O VFS permite que esses sistemas de arquivos atuem diretamente no campo s_fs_info do superbloco em memória sem precisar acessar o disco.
super_operations - Uma estrutura muito importante do Objeto Superbloco é s_op definido como uma estrutura super operations, onde encontram-se ponteiros para funções que operam sobre o Objeto Superbloco.
Quando deseja-se realizar uma operação sobre um Superbloco, o Sistema de Arquivos segue os ponteiros até o método que se deseja executar:
sb -> s_op -> write_super(sb);
-onde sb é um ponteiro para o Superbloco do Sistema de Arquivos em questão, s_op produzirá uma tabela de operações para o superbloco e write_super() a função específica executada.
Objeto Inode
Um Objeto Inode possui toda informação necessária para que o Sistema de Arquivos possa manipular os arquivos e/ou diretórios. Cada arquivo é representado por um inode no Sistema de Arquivos. O Objeto Inode é instanciado no momento de abertura do arquivo ( acesso ). Um nome de arquivo é um identificador que pode ser alterado, mas o inode é único para o arquivo e permanece o mesmo enquanto o arquivo existir. Um Objeto Inode em memória consiste de uma estrutura inode cujos campos podem ser vistos clicando em qualquer nome Objeto Inode. Cada Objeto desse tipo duplica algumas das infornações incluídas no inode do disco como por exemplo o número de blocos alocados para o arquivo. Quando o valor do campo i_state é igual a I_DIRTY_SYNC, I_DIRTY_DATASYNC ou I_DIRTY_PAGES, significa que o respectivo inode está sujo, ou seja, é necessário que o inode correspondente no disco seja atualizado. I_DYRTY pode ser usada para se verificar o valor desses três campos ao mesmo tempo.
Em um terminal de comando, como o xterm, podemos ver qual é o número de i-node de um certo arquivo, ou diretório. Para entender a árvore de arquivos que o Linux possui, o Linux atribui o número '1' para o i-node do diretório raíz '/'. Dentro desta estrutura, todos os arquivos e diretórios possuem um i-node. Sendo assim, qualquer arquivo ou diretório dentro de um sistema de arquivo Linux e, por fim, usando o Virtual File System, percorrendo desde o diretório raiz, e assim por diante. Um exemplo será mostrado a seguir:
...@so171:~$ ls -lai / [...] 2 drwxr-xr-x 23 root root 4096 2007-04-20 10:36 . 2 drwxr-xr-x 23 root root 4096 2007-04-20 10:36 .. 703137 drwxr-xr-x 107 root root 4096 2007-05-16 08:07 etc 1 dr-xr-xr-x 98 root root 0 2007-05-16 05:07 proc [...]
Note que os '..', significa o diretório pai, com inode '2' (raiz) e o '.', significa o diretório corrente, com inode 2, isto pois o diretório raiz não tem pai.
inode operations descreve as funções implementadas que o VFS pode chamar em um i-node.
Objeto Dentry
O VFS trata diretórios como arquivos. Exemplo: /bin/vi, bin e vi são arquivos, ambos representados pelo objeto inode. Para facilitar a realização de operações específicas sobre diretórios, o VFS usa o conceito de "entrada de diretório" (dentry). O dentry é um componente específico do path. No exemplo, /, bin e vi são objetos dentry. O VFS instancia estes objetos "on the fly", quando há a necessidade de realizar operações sobre diretórios. Os objetos dentry podem portanto ser diretórios, arquivos ou até pontos de montagem.
Ao contrário das demais estruturas vistas anteriormente, o objeto dentry não corresponde a qualquer estrutura de dados armazenada em disco. O VFS cria este objeto "on the fly", a partir da string de representação do path.
Há uma flag, “Dentry State”, que indica o status de um objeto dentry:
Usado – corresponde a um inode válido e indica que há um ou mais usuários para aquele objeto
Não usado – o VFS não está usando o objeto no momento, apesar do inode correspondente ser válido.
Negativo – o objeto está associado a um inode inválido porque o inode foi apagado ou porque o path sequer jamais exisitiu.
Objeto File
A representação dos arquivos abertos pelos processos é feita pelo File Object
Um File Object descreve como um processo interage com o arquivo que foi aberto. O objeto é criado quando o arquivo é aberto e consiste em uma estrutura de arquivo, cujos campos pode ser vistos clicando em File Object.
A informação mais relevante guardada em um file object é file pointer, que indica a posição no arquivo em que a próxima operação se iniciará. Pelo fato de vários processos poderem acessar o mesmo arquivo de forma concorrente, o ponteiro para a posição no arquivo deve ser mantido no file object e não no inode object.
Como os outros objetos tais como o Superbloco, dentry e inode, o File object também tem suas operações que são definidas em file operations.
Relacionamento entre as estruturas do núcleo
Estruturas de Dados Associadas aos File System
File System Type
A estrutura especial que o núcleo utiliza para descrever as capacidades e o comportamento de cada sistema de arquivos é o file system type.
Dentre as funções do file system type, a mais importante é a get_sb() que é usada para ler o superbloco no disco e preencher o objeto de supebloco quando o sistema de arquivos é carregado. As outras funções descrevem as propriedades do sistema de arquivos. Cada sistema de arquivo possui apenas um file system type independentemente de quantas instâncias do sistemas estão montadas ou ainda se o sistema foi realmente montado.
Vfsmount
Objeto criado no momento em que o sistema de arquivos é montado. É usado para representar uma instância montada, específica, de um sistema de arquivos. Esta estrutura está definida em <linux/mount.h>
Estruturas de dados associadas a um Processo
Files Struct
Estrutura apontada na entrada "files" no descritor do processo. Contém uma variável (array "fd") que aponta para a lista de arquivos abertos por aquele processo. Este array tem 32 entradas,mas outro array pode ser alocado pelo Núcleo, em tempo de execução, caso o processo necessite acessar mais arquivos.
Fs_struct
Estrutura apontada no campo "fs" no descritor do processo, que contém informações do sistema de arquivos relacionadas ao processo, tais como o diretório corrente de trabalho e o diretório raiz do processo.
Namespace
Estrutura apontada no campo “namespace” no descritor do processo, que possibilita que cada processo tenha uma visão única do sistema de arquivos montado. À cada processo é dada uma cópia do namespace (filesystem hierarchy).
Funções
register filesystem
Cada rotina de inicialização do sistema de arquivo se registra no Sistema de Arquivo Virtual e é representado por uma estrutura file_system_type que contem o nome do sistema de arquivo e um ponteiro para sua rotina de leitura do VFS . Cada dados de estrutura file_system_type contém as seguintes informações:
Rotina de leitura do Superblock
Esta rotina é chamada pelo VFS quando um solicitação do sistema de arquivo é montado.
Nome do Arquivo de Sistema
O nome deste sistema de arquivo, por exemplo ext2.
Dispositivo necessários
Este sistema de arquivo necessita um dispositivo para suporte? Nem todo sistema de arquivo necessita um dispositivo para suporte. O sistema de arquivo /proc, por exemplo, não requer um dispositivo de bloco.
start kernel -> proc root init -> register filesystem
Montagem
Quando o superusuário tenta montar um sistema de arquivo, o Linux deve primeiro validar os argumentos passados na chamada de sistema. Embora mount faz algumas checagem básicas, ele não sabe que sistemas de arquivos este núcleo tem suporte ou que o lugar de montagem proposto exista. Considere o seguinte comando mount:
$ mount -t iso9660 -o ro /dev/cdrom /mnt/cdrom
Este comando mount passa ao núcleo três informações; o nome do sistema de arquivo, o dispositivo de bloco físico que contém o sistema de arquivo e, em terceiro lugar, onde na topologia do sistema de arquivos está o novo sistema de arquivo a montar.
A primeira coisa que o Sistema de Arquivo Virtual deve fazer é encontrar o sistema de arquivo.
Se é encontrado um nome, ele agora sabe que este tipo de sistema de arquivo é suportado por este núcleo e tem o endereço da rotina especifica para leitura do superblock do sistema de arquivo.
Caminho percorrido até a montagem do sistema
mount( ) -> sys mount -> do mount -> do new mount -> do add mount -> graft tree
Abertura de arquivo
A chamada de sistema open() usa os serviços oferecidos pela função sys_Open(), que recebe como parâmetros o caminho filename e o arquivo a ser aberto.Alguns flags que indicam o modo de acesso e um bit de permissão mode se o arquivo deve ser criado. Se a chamada de sistema retornar sucesso , ela retorna um descritor de arquivo, isto é, o indice no vetor de ponteiros do objeto file current->file->fd, caso contrário , ele retorna -1.
Caminho percorrido até a abertura do arquivo
open() -> sys open -> filp open -> open namei -> path lookup
Escrita e Leitura de arquivo
Chamada de sys write -> vfs write.
Chamada de sys read -> vfs read.
Veja também
Referências
- ↑ Werner Fischer; Georg Schönberger (1 de junho de 2015). «Linux Storage Stack Diagram». Thomas-Krenn.AG. Consultado em 8 de junho de 2015
- AVFS - Sistema de arquivos virtual para montagem comprimida ou arquivos remotos.
- fs-driver Sistema de arquivos Ext2 instalável para Microsoft Windows.
- GMail Filesystem para Linux, basedo no FUSE dependente de libgmail.
- FUSE - Filesystem in Userspace - virtual filesystem para Linux.