Nesse laboratório vamos explorar a interface com o sistema operacional.
Para começar, pegue o
programa em C, que copia o arquivo dado na linha
de comando para a saída padrão (tela), e
salve-o em um arquivo copia.c
.
Compile e execute esse programa, testando-o com algum
arquivos de entrada (pode ser o próprio arquivo copia.c
):
> gcc -Wall -o copia copia.c
> ./copia copia.c
copia.c
.
A rotina main
chama quatro funções definidas neste
mesmo arquivo: myopen
, myread
, mywrite
e myclose
.
Cada uma dessas funções é implementada por uma única linha, que
contém uma chamada ao sistema operacional (na verdade, uma
chamada a uma função wrapper, provida pela biblioteca padrão de C).
As chamadas ao sistema operacional são documentadas na seção 2 do manual
do Linux.
Para ver a documentação de uma delas, basta escrever, por exemplo:
> man 2 open
myopen
, myread
, mywrite
e myclose
)
por funções equivalentes a elas, escritas em assembly.
Atenção: suas funções assembly não devem chamar as funções da biblioteca de C! Elas devem usar uma interface direta com o SO.
Crie um arquivo chamadas.s
,
e comece substituindo a função myopen
.
Comente a definição dessa função
no arquivo copia.c
, mantendo o seu protótipo.
Implemente myopen
em assembly (ver instruções abaixo), e compile tudo agora com:
> gcc -Wall -o copia chamadas.s copia.c
Para descobrir o código das chamadas ao sistema, consulte esta
tabela de chamadas.
Observe os seguinte pontos:
syscall
copia.c
e substituindo-as pela
implementação em assembly em chamadas.s
.
A implementação em assembly de chamadas a serviços do sistema
operacional que você acabou de fazer é
semelhante à implementação das funções wrapper
disponíveis na biblioteca padrão de C.
myotherwrite
,
que receba um descritor
de arquivo e uma string, e
escreva essa string string no arquivo fornecido:
int myotherwrite (int fd, char *s);Para testar sua função, você pode usar o código abaixo:
#include <fcntl.h> #include <stdio.h> #include <unistd.h> #define MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH) ssize_t myotherwrite(int fd, const void *buf); int main (int argc, char** argv) { ssize_t tam; int arq; char buf[] = "testando escrita direta\n"; if (argc != 2) { fprintf(stderr,"forma correta: %s\n", argv[0]); return 1; } arq = open (argv[1], O_CREAT|O_RDWR, MODE); if (arq<0) { perror("abertura de arquivo"); return 1;} if ((tam = myotherwrite (arq, buf)) != sizeof(buf)-1) { perror("escrita:"); return 1; } close (arq); return 0; }