MC504/MC514 - Sistemas Operacionais
Implementação de Chamadas de Sistema
Dicas
Veja algumas dicas aqui.
Importante: No laboratório, USE O TMP!
Atenção: como o espaço em disco utilizado durante
este experimento é muito grande, caso os testes sejam feitos no
laboratório deveremos utilizar o diretório /tmp
das máquinas.
$ mkdir /tmp/raXYZXYZ
$ cd /tmp/raXYZXYZ
Assim, você não esgota a sua quota e não
prejudica o desempenho da rede para os outros. Pelos mesmos motivos,
antes da compilação do kernel, configure o
diretório CCACHE utilizando o comando:
$ export CCACHE_DIR="/tmp/.ccache"
Ambiente de testes
QEMU
O QEMU é um virtualizador
e emulador de processadores. Podemos fazer um teste bem simples com o
QEMU utilizando
a imagem
disponível
em Testing
QEMU .
qemu-system-i386 -hda linux-0.2.img
Teste com o kernel 4.8.6
- Obtenha a versão 4.8.6 ou outra verão recente do
kernel em kernel.org. Execute a
descompactação com o comando:
$ pwd
/tmp/raXYZXYX
$ wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.8.6.tar.xz
$ tar xJvf linux-4.8.6.tar.xz
- Obtenha a imagem ArchLinux_mc504.cow que
foi criada por Tiago Gimenes
no
1s2016. Esta imagem contém o gcc e é um
pouco maior e mais completa do que a imagem utilizada em semestres
anteriores.
- Obtenha o arquivo de
configuração config-4.8.6
adequeado para rodar com o QEMU.
- Instale o arquivo de configuração e compile o kernel.
$ cd linux-4.5.8
$ cp ../config-4.5.8 .config
$ make -j 5 ARCH=i386
- Teste o kernel com a imagem utilizando o QEMU:
$ qemu-system-i386 -hda ArchLinux_mc504.cow -kernel linux-4.8.6/arch/i386/boot/bzImage -append "rw root=/dev/hda"
- Quando o sistema entrar poderemos fazer login com usuário root, sem senha.
- Para sair sem corromper a imagem:
$ poweroff
Primeira chamada
Antes de fazermos uma chamada de sistema mais elaborada, vamos testar
uma que não recebe parâmetros e retorna uma
constante. Chamaremos esta chamada de mycall.
- Alterar a
tabela linux-4.8.6/arch/x86/entry/syscalls/syscall_32.tbl,
acrescentando uma nova linha ao final do arquivo:
380 i386 mycall sys_mycall
- Incluir uma declaração da
função sys_mycall
em um ponto adequado do arquivo linux-4.8.6/include/linux/syscalls.h
asmlinkage long sys_mycall(void);
- Incluir o código para função no
diretório linux-4.8.6/arch/x86/kernel/. Podemos utilizar o
arquivo mycall.c, cujo conteúdo é:
#include <linux/unistd.h>
#include <linux/linkage.h>
asmlinkage long sys_mycall(void) {
return(4096);
}
- Alterar o Makefile do
diretório linux-4.8.6/arch/x86/kernel/, incluindo uma linha:
obj-y += mycall.o
- No diretório linux-4.8.6 executar
$ make -j 5 ARCH=i386
- Escrever um programa para testar a chamada em modo
usuário. Pode ser um programa bem simples
como ex-mycall.c:
/*
* Teste da nova chamada de sistema
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
int r = syscall(380);
printf("Retorno da chamada de sistema: %d.\n", r);
return r;
}
- Devemos tornar este código visível para o QEMU. Uma
opção simples é exportar o arquivo que
contém o código como um disco:
$ qemu-system-i386 -hda ArchLinux_mc504.cow -kernel linux-4.8.6/arch/i386/boot/bzImage -append "rw root=/dev/hda" -drive format=raw,file=ex-mycall.c
Após logar no sistema, devemos executar os comandos
abaixo. O gcc irá ignorar os caracteres nulos adicionados no
processo.
$ cat /dev/hdb > ex-mycall.c
$ gcc ex-mycall.c -o ex-mycall
$ ./ex-mycall
- Outra opção é criar um mini sistema de
arquivos. O debugfs será utilizado porque não temos permissão
de root nas máquinas do laboratório.
$ dd if=/dev/zero of=ext2.dmp bs=1k count=100
$ mkfs.ext2 ext2.dmp
$ debugfs -w ext2.dmp
debugfs: write ex-mycall.c ex-mycall.c
debugfs: quit
$ qemu-system-i386 -hda ArchLinux_mc504.img -kernel linux-4.8.6/arch/i386/boot/bzImage -append "rw root=/dev/hda" -drive format=raw,file=ext2.dmp
Após logar no sistema, devemos executar:
$ mkdir mnt
$ mount -t ext2 /dev/hdb mnt
$ cd mnt
$ gcc ex-mycall.c -o ex-mycall
$ ./ex-mycall
Projeto 2: Chaves temporárias
Você deverá implementar uma chamada de sistema que receba pares de
chave/valor com tempo de vida determinado no momento da criação. A
chave deve ser um parâmetro inteiro e o valor uma cadeia de
caracteres. Crie as chamadas de sistema gettmpkey
e settmpkey para armazerar e recuperar estes pares de
chave/valor. Você precisará fazer também um programa em C para testar
as suas novas chamadas de sistema.
- settmpkey:
/* Retorna 0 se a operação foi bem sucedida e -1 caso contrário. */
asmlinkage long sys_settmpkey(int key, char* value, unsigned int lifespan);
- gettmpkey:
/* Copia em value o valor da chave key com no máximo n caracteres.
Retorna 0 se encontrou chave válida e -1 caso contrário. */
asmlinkage long sys_gettmpkey(int key, int n, char* value);
- Para verificar o tamanho e armazenar a chave no espaço de
kernel, você deve utilizar as funções strnlen_user
e strncpy_from_user como descrito
em User
space memory access from the Linux kernel (versão em português
Acesso
à memória do espaço do usuário a partir do kernel Linux).
- Você deve utilizar uma tabela de hash com resolução de
colisões via lista ligada. Utilize as funções kmalloc
e kfree.
- Para verificar o tempo de vida da chave, utilize a variável
jiffies e a constante HZ. Não é necessário se
preocupar com overflow.
Entrega: 14 de dezembro via Moodle. Apresentação obrigatória no lab por pelo menos um membro do grupo.