Níveis de Operação de Arquivos e Chamadas de Sistema em Sistemas Operacionais

1. Nível de Hardware

As operações de arquivo no nível de hardware incluem:

  • fdisk: particionar discos rígidos, drives USB ou cartões SD.
  • mkfs: formatar partições de disco para preparar o sistema.
  • fsck: verificar e reparar o sistema de arquivos.
  • Desfragmentação: comprimir arquivos dentro do sistema de arquivos.

2. Funções de Sistema de Arquivos no Kernel do Sistema Operacional

Cada kernel do sistema operacional fornece suporte para operações básicas de arquivo através de funções integradas.

3. Chamadas de Sistema

Programas em modo de usuário utilizam chamadas de sistema para acessar funções do kernel.

4. Funções de Biblioteca I/O

Bibliotecas de I/O oferecem uma camada de abstração sobre as chamadas de sistema.

5. Comandos do Usuário

Usuários podem executar operações de arquivo usando comandos do Unix/Linux sem necessidade de programação. Exemplos incluem:

mkdir, rmdir, cd, pwd, ls, link, unlink, rm, cat, cp, mv, chmod, etc.

Cada comando de usuário é tipicamente um programa executável que invoca funções de biblioteca I/O, que por sua vez emitem chamadas de sistema para chamar as funções do kernel correspondentes.

Operações de I/O de Arquivo

Quando um programa em modo de usuário executa uma operação de I/O:

  1. Uma chamada como fopen("arquivo", "r") abre um fluxo de arquivo para leitura ou escrita.
  2. A função fopen() cria uma estrutura FILE no espaço do usuário (heap), contendo um descritor de arquivo fd, um buffer fbuf[BLKSIZE] e variáveis de controle.
  3. A função fread(ubuf, size, nitem, fp)nitem elementos de size bytes para ubuf. Primeiro, copia dados do fbuf da estrutura FILE para ubuf; se os dados forem suficientes, retorna. Caso contrário, procede para a etapa de leitura do kernel.
  4. Uma chamada de sistema read(fd, fbuf, BLKSIZE) é emitida para carregar um bloco de dados do arquivo do kernel para o fbuf, e os dados são então copiados para ubuf até serem suficientes ou o arquivo terminar.
  5. Para fwrite(ubuf, size, nitem, fp): os dados são copiados de ubuf para fbuf. Se o fbuf tiver espaço, os dados são armazenados e a função retorna. Se o fbuf estiver cheio, uma chamada de sistema write(fd, fbuf, BLKSIZE) é usada para gravar o bloco de dados no kernel, e então os novos dados são escritos no fbuf.

Assim, fread() e fwrite() emitem chamadas de sistema read ou write somente quando necessário, transferindo dados em tamanhos de bloco para eficiência. Outras funções de biblioteca I/O, como fgetc/fputc, fgets/fputs, fscanf/fprintf, também operam no fbuf da estrutura FILE no espaço do usuário.

Funções de Sistema de Arquivos no Kernel

Para uma chamada de sistema read(fd, fbuf[], BLKSIZE) em um arquivo não especial:

  • O fd é um descritor de arquivo aberto, um índice no array f do processo em execução, apontando para uma tabela aberta de arquivos (OpenTable).
  • A OpenTable contém o modo de abertura do arquivo, um ponteiro para o inode do arquivo na memória e o deslocamento atual de leitura/escrita.
  • A partir do deslocamento na OpenTable, o número lógico do bloco lbk é calculado. O array INODE.i_block[] converte o número lógico do bloco no número físico do bloco blk.
  • O Minode contém o inode do arquivo na memória, com INODE.i_block[] apontando para blocos físicos no disco.

Para aumentar a eficiência de I/O de disco, o kernel do sistema operacional normalmente usa um conjunto de buffers de I/O como cache para reduzir o número de operações físicas de I/O. Por exemplo:

  • Para read(fd, buf, BLKSIZE), determina-se o número (dev, blk) necessário e consulta-se a cache de buffers de I/O.
  • Para write(fd, fbuf, BLKSIZE), determina-se o número (dev, blk) necessário e consulta-se a cache de buffers de I/O.

I/O de Dispositivo

A operação física de I/O nos buffers passa pelos drivers de dispositivo, que são compostos pela parte superior start_io() e pelo manipulador de interrupção de disco inferior.

Operações de Arquivo de Baixo Nível

  • Particionamento de discos.
  • Formatação de partições.
  • Montagem de partições.

Chamadas de Sistema Simples

Exemplos de chamadas de sistema para operações comuns incluem:

  • access: verifica permissões de arquivo.
  • chdir: altera o diretório de trabalho.
  • chmod: altera as permissões de um arquivo.
  • chown: altera o proprietário de um arquivo.
  • chroot: altera o diretório raiz lógico.
  • getcwd: obtém o caminho absoluto do diretório de trabalho atual.
  • mkdir: cria um diretório.
  • rmdir: remove um diretório vazio.
  • link: cria um hardlink para um arquivo.
  • unlink: reduz a contagem de links de um arquivo; se chegar a zero, o arquivo é removido.
  • symlink: cria um link simbólico para um arquivo.
  • rename: renomeia um arquivo.
  • utime: altera os tempos de acesso e modificação de um arquivo.

Algumas chamadas de sistema requerem privilégios de superusuário:

  • mount: anexa um sistema de arquivos a um ponto de montagem.
  • umount: desanexa um sistema de arquivos montado.
  • mknod: cria um arquivo especial.

Chamadas de Sistema Comuns para I/O

  • stat: obtém informações de estado de um arquivo.
  • open: abre um arquivo para leitura, escrita ou anexação.
  • close: fecha um descritor de arquivo aberto.
  • read: lê de um descritor de arquivo aberto.
  • write: escreve em um descritor de arquivo aberto.
  • lseek: reposiciona o deslocamento de leitura/escrita de um descritor de arquivo.
  • dup: duplica um descritor de arquivo para o menor número disponível.
  • dup2: duplica um descritor de arquivo para um número específico, fechando o destino se necesssário.
  • link: cria um hardlink de um novo caminho para um caminho antigo.
  • unlink: remove um link de arquivo; se a contagem de links chegar a zero, o arquivo é deletado.
  • symlink: cria um link simbólico.
  • readlink: lê o conteúdo de um arquivo de link simbólico.
  • umask: define a máscara de criação de arquivo; permissões do arquivo são (mask & ~umask).

Chamada de Sistema read

A chamada de sistema read lê dados de um arquivo identificado por um descritor de arquivo, armazenando-os em um buffer pré-definido. Ela retorna o número de bytes realmente lidos.

Protótipo no Linux:

size_t read(int fildes, void *buf, size_t nbytes);

Parâmetros:

  • fildes: descritor de arquivo, identificando o arquivo a ser lido. Se for 0, lê da entrada padrão (similar a scanf()).
  • *buf: buffer para armazenar os dados lidos.
  • nbytes: número de bytes a serem lidos.

Valor de retorno: size_t retorna o número de caracteres lidos com sucesso, que pode ser menor que o solicitado.

Chamada de Sistema write

A chamada de sistema write grava dados de um buffer em um arquivo, onde "arquivo" pode ser entendido em sentido amplo, como disco, impressora, etc.

Protótipo no Linux:

size_t write(int fildes, const void *buf, size_t nbytes);

Parâmetros:

  • fildes: descritor de arquivo, identificando o destino da escrita. Por exemplo, se for 1, escreve na saída padrão (exibição na tela); se for 2, escreve na saída de erro.
  • *buf: ponteiro para a string de dados a serem gravados.
  • nbytes: número de bytes a serem escritos.

Valor de retorno: size_t retorna o número de bytes gravados com sucesso. Note que write pode reportar ter escrito menos bytes do que solicitado; isso não é necessariamente um erro. Em programas, deve-se verificar erros e chamar write novamente para os dados restantes, se necessário.

Tags: Linux system calls File I/O Operating Systems C programming

Publicado em 7-23 15:47