31
16 de Jul de 2008 1 Antônio Augusto Fröhlich (http://www.lisha.ufsc.br) Introdução ao Desenvolvimento com LINUX: Módulos do Kernel Lucas Wanner, Antônio Augusto Fröhlich [email protected] http://www.lisha.ufsc.br/~guto 16 de Jul de 2008

Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

  • Upload
    others

  • View
    16

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 1Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Introdução ao Desenvolvimentocom LINUX: Módulos do Kernel

Lucas Wanner, Antônio Augusto Frö[email protected]

http://www.lisha.ufsc.br/~guto

16 de Jul de 2008

Page 2: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 2Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Desmotivação para Desenvolver Software de Sistema Já temos Windows e Unix e MacOS!

● Que são sistemas multiusuário, multitarefa com interfa­ces gráficas legais que nos permitem acessar a Web...

● E fazem uso de modernas técnicas de engenharia de software, como programação estruturada!

● E há inúmeras histórias de SOs fracassados ... E temos ótimos padrões de SO!

● APIs fortes como Posix e Win32 ● Hardware se fixando na novíssima arquitetura IA­32● Como disse Pike: pesquisa em SO é irrelevante!

Page 3: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 3Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Motivação para Desenvolver Software de Sistema

Where are the processors?(Tennenhouse, CACM 43(5):44)

interactive2%

robots6%

vehicles12%

embedded80%

8­bit63%

16­bit12%

>= 32­bit3%

4­bit22%

Sistemas de propósito geral● Prontos para o que der e vier

●Qualquer aplicação● Muitos serviços

Sistemas dedicados● Aplicações particulares● Requisitos específicos e 

poucos serviços● São a grande MAIORIA!

Page 4: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 4Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Sistemas Dedicados na Forma de Placas PCI

Page 5: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 5Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Drivers de dispositivos “Caixa preta” que esconde a interação com o 

hardware atrás de uma interface de software comum (API/SPI)

Implementados através de módulos carregáveis no kernel dos UNIXes modernos (e.g. LINUX)

Page 6: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 6Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Kernel LINUX

Page 7: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 7Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Kernel LINUX

Page 8: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 8Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Drivers de dispositivos no LINUX API inspirada em arquivos●Dispositivos representados por pseudo arquivos●Operações típicas de arquivos●Open / Close, Read / Write

Implementados através de módulos carregáveis ou lincados diretamente ao kernel

Categorias● Dispositivos orientados à caractere● Dispositivos orientados a bloco● Dispositivos de rede

Page 9: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 9Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Pseudo Arquivos deDispositivos de Hardware Por convenção, no diretório /dev Kernel redireciona as operações realizadas nos 

pseudo arquivos para os serviços correspondentes do driver do dispositivo

Pseudo­arquivos são “amarrados” com os dispositivos através dos números major e minor 

Page 10: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 10Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Pseudo Arquivos deDispositivos de Hardware Número Major

● Identifica o driver (módulo) que deve ser acessado● Número de 8 bits

Número Minor● Identifica o dispositivo (unidade) dentro do contexto do 

módulo Exemplo

● Driver IDE:  major = 3● Primeira partição do primeiro disco IDE: minor = 1

Page 11: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 11Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Dispositivos Orientados à Caractere Vistos como fluxos de bytes Operação similar a arquivos comuns

● Exceção: não é possível avançar/retroceder na leitura/escrita (i.e. seek)

Exemplos● /dev/console● /dev/ttyS0

Page 12: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 12Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Dispositivos orientados a blocos Dispositivos que, durante as operações de I/O, 

acessam dados em blocos Dispositivos relacionados com sistemas de 

arquivos (e.g. discos) Interface comum com dispositivos orientados à 

caractere, mas com semântica distinta● Orientados a blocos● Poder avançar ou retroceder a leitura/escrita

Operações adicionais para suportar sistemas de arquivos

Page 13: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 13Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Dispositivos de Rede Não se encaixam no esquema de pseudo­

arquivos● Geralmente não são um nodo no sistema de arquivos● Integrados a uma pilha de protocolos

Interface de rede genérica● Operações relacionadas a comunicação (e.g. envio de 

dados, recepção, manipulação de time­outs, agrupamento de estatísticas)

● Otimizada para integração a pilha TCP/IP

Page 14: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 14Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Inicialização de Módulos Inicialização

● int init_module(void)●Ponto de entrada do módulo●Chamado na carga (pelo comando insmod)●Registra o módulo no kernel

Finalização● void cleanup_module(void)

●Ponto de saída do módulo●Chamado na finalização (pelo comando rmmod)●Deregistra o módulo

Page 15: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 15Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Compilação de Módulos Sistema de compilação do Kernel 2.6

● Usa um sistema estendido de “make” com Makefiles simplificados para os drivers:

● Compilando módulos de fora da árvore do kernelmake -C $LINUX_SRC/ M='pwd' modules

● Exige uma árvore configurada do kernel!

$ cat Makefile obj-m := hello.o

Page 16: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 16Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Compilando o Kernel LINUX Preparação

● Pacotes necessários●sudo apt-get install linux-kernel-devel

fakeroot qt3-dev-tools libqt3-mt-dev  (Ubuntu)● Download do código fonte do kernel

●sudo apt-get install linux-source (Ubuntu)●Download disponível em kernel.org

● Criação de diretório para compilação●mkdir ~/src●cd ~/src●tar xjvf /usr/src/linux-source-VERSAO.tar.bz2●cd linux-source-VERSAO

Page 17: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 17Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Compilando o Kernel LINUX Processo de Compiliação

● Cópia da configuração atual●cp -vi /boot/config-`uname -r` .config

● Configuração●make xconfig

● Compilação●make

● Utilização do kernel compilado (não é necessário para compilar os módulos)●make kernel-image●Atualização da configuração do bootloader

Page 18: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 18Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Exercício: Hello Module Crie um módulo “Hello World”

● Defina as funções de entrada e saída do módulo:●static int hello_init(void)●static void hello_exit(void)

● No corpo destas funções, imprima uma mensagem●Exemplo: printk(KERN_ALERT "Hello, world.\n");

● Registre as funções com as macros module_init(x) e module_exit(y)

● Crie um módulo “Hello World”● Headers

●#include <linux/init.h>, #include <linux/module.h>

Page 19: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 19Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Exercício: Hello Module

#include <linux/init.h> #include <linux/module.h>

static int hello_init(void) { printk(KERN_ALERT "Hello, kernel\n"); return 0; }

static void hello_exit(void) { printk(KERN_ALERT "Goodbye, kernel\n"); }

module_init(hello_init); module_exit(hello_exit);

Page 20: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 20Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Exercício: Hello Module

$ ls hello.c Makefile

$ make -C /lib/modules/`uname -r`/build M=`pwd` modules make: Entering directory `~/src/linux-source-2.6.24' CC [M] /home/lucas/tmp/linux-dev/modules/hello/hello.o Building modules, stage 2. MODPOST 1 modules CC /home/lucas/tmp/linux-dev/modules/hello/hello.mod.o LD [M] /home/lucas/tmp/linux-dev/modules/hello/hello.ko make: Leaving directory `~/src/linux-source-2.6.24'

$ ls hello.c hello.ko hello.mod.c hello.mod.o hello.o Makefile Module.symvers

Page 21: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 21Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Hello Module: Saída Saída gerada pela biblioteca do kernel (método printk)

Mensagens visíveis através do comando dmesg $ sudo insmod hello.ko

$ dmesg | grep Hello [ 9326.866732] Hello, kernel

$ sudo rmmod hello

$ dmesg | grep Goodbye [ 9356.192375] Goodbye, kernel

Page 22: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 22Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Hello Module: Trace Quando insmod é chamado, o kernel

● Aloca memória para o módulo● Abre o arquivo que contem o código● Lê o arquivo para a memória alocada● Chama o método init_module() 

Page 23: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 23Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Hello Module: Trace sudo strace insmod hello.ko execve("/sbin/insmod", ["insmod", "hello.ko"], [/* 16 vars */]) = 0 brk(0) = 0x804a000 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f0a000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=78806, ...}) = 0 mmap2(NULL, 78806, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7ef6000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/tls/i686/cmov/libc.so.6", O_RDONLY) = 3 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\260e\1"..., 512) = 512 fstat64(3, {st_mode=S_IFREG|0755, st_size=1364388, ...}) = 0 mmap2(NULL, 1369712, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7da7000 mmap2(0xb7ef0000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x149) = 0xb7ef0000 mmap2(0xb7ef3000, 9840, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7ef3000 close(3) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7da6000 set_thread_area({entry_number:-1 -> 6, base_addr:0xb7da66b0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 mprotect(0xb7ef0000, 4096, PROT_READ) = 0 munmap(0xb7ef6000, 78806) = 0 brk(0) = 0x804a000 brk(0x806b000) = 0x806b000 open("hello.ko", O_RDONLY) = 3 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\1\0\3\0\1\0\0\0\0\0\0\0"..., 16384) = 16384 read(3, "\0\0\rM\1$\0\0\0\3#\354@\32\325\31\0\0\rN\1\3\n\0\0\3#"..., 16384) = 16384 read(3, "r_cpu_pages\0___vm86_gs\0io_bitmap"..., 32768) = 17068 read(3, "", 15700) = 0 close(3) = 0 init_module(0x804a018, 49836, "") = 0 exit_group(0) = ? Process 29221 detached

Page 24: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 24Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Registro de Módulos Liga um módulo à interface de chamadas de 

sistema do kernel Registro

● int register_chrdev(unsigned int major, const char *name, struct file_operations *fops)

Deregistro● int unregister_chrdev(unsigned int major, const char *name)

Pseudo­arquivo● mknod /dev/devname0 c major minor

Page 25: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 25Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Parâmetros do Módulo Variáveis globais acessíveis externamente

● Declaradas através da macro MODULE_PARM(variavel, tipo, permissões)

int irq = 10;char * name = “Unknown”;/*declara irq como int */MODULE_PARM(irq, ”i”, 0); /*declara name como string */MODULE_PARM(name, ”s”, 0);

Definidas em tempo de cargainsmod mod.o irq=9 name= ”The Module”

Page 26: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 26Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Informações do Módulo Declarações do módulo visíveis externamente, 

que fornecem informações aos clientes do módulo

MacrosMODULE_LICENSE("GPL");MODULE_AUTHOR("Alguem");MODULE_DESCRIPTION("Este modulo não faz nada");

MODULE_PARM_DESC(irq, "Device IRQ (3/4)"

Page 27: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 27Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Operações de arquivo

struct file_operations { struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char *, size_t, loff_t *); ssize_t (*write) (struct file *, const char *, size_t, loff_t *); int (*readdir) (struct file *, void *, filldir_t); unsigned int (*poll) (struct file *, struct poll_table_struct *); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*flush) (struct file *); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, struct dentry *, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); : : };

Page 28: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 28Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Estrutura arquivo

struct file { struct list_head f_list; struct dentry *f_dentry; struct vfsmount *f_vfsmnt; struct file_operations *f_op; atomic_t f_count; unsigned int f_flags; mode_t f_mode; loff_t f_pos; unsigned long f_reada, f_ramax, f_raend,f_ralen,f_rawin; struct fown_struct f_owner; unsigned int f_uid, f_gid; int f_error; : };

MINOR(f_dentry->d_inode->i_rdev)

Page 29: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 29Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Contador de Referências Contador de Referências do Módulo

● Contabiliza automaticamente o número de clientes que um módulo tem em um determinado momento

● Evita que um modulo que está sendo utilizado seja descarregado

Manipulado pelas funções:● int try_module_get(&module);● module_put();

Page 30: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 30Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Gerência de Memória Código do kernel roda no contexto do processo 

de usuário que fez a chamada#include <asm/uaccess.h>unsigned long copy_to_user(to, from, count);unsigned long copy_from_user(to, from, count);

Alocação de memória dentro do kernel#include <linux/malloc.h>void *kmalloc(unsigned int size, int priority);void kfree(void *obj);

Page 31: Introdução ao Desenvolvimento com LINUX: Módulos do Kernel · Compilando o Kernel LINUX Preparação Pacotes necessários sudo apt-get install linux-kernel-devel fakeroot qt3-dev-tools

16 de Jul de 2008 31Antônio Augusto Fröhlich (http://www.lisha.ufsc.br)

Dicas de Programação Não utilizar bibliotecas (e cabeçalhos) padrão

● printk no lugar de printf#include <linux/x.h>#include <asm/y.h>

Sinalizar código de kernel● #define __KERNEL__

Evitar conflitos de nomes● Símbolos locais (static)● Símbolos pré­fixados (mod_sym)EXPORT_NO_SYMBOLS;