Universidade Federal de Ouro Preto Departamento de Computação e Sistemas - DECSI Desenvolvimento para Sistemas Embarcados (CEA 513) Sistema de Arquivos Raiz & Vicente Amorim vicente.amorim.ufop@gmail.com
Sumário * Sistema de Arquivos Básico e Bibliotecas * Componentes do kernel
Sistema de Arquivos Básico e Bibliotecas
Sistema de Arquivos Básico e Bibliotecas * O comportamento do SO Linux para embarcados se difere em muito das versões para desktop/servidores. * Em cada caso, um sistema de arquivos mínimo deve ser considerado. * Algumas funções da versão completa não precisam estar presentes. * Na versão para embarcados o sistema de arquivos básico do SO tende a ser menor e mais compacto.
Sistema de Arquivos Básico e Bibliotecas * Sistema de arquivos básico (completo):
Sistema de Arquivos Básico e Bibliotecas * Na versão para embarcados, alguns dos diretórios podem ser removidos: - Suporte a multi-usuários: /opt, /home, /root e /mnt. - Versão minimalista: /var e /tmp. (problemas podem ocorrer) - Diretórios restantes são essenciais: /bin, /dev, /etc, /lib, /proc, /sbin e /usr. - Em casos extremos o diretório /proc pode ser omitido: Pode tornar difícil a depuração de algum problema posteriormente.
Sistema de Arquivos Básico e Bibliotecas * Aparente redundância do sistema de arquivos: - Binários do sistema podem estar localizados em: /bin, /sbin, / usr/bin e /usr/sbin. - Local de armazenamento depende do papel que o mesmo desempenha no sistema: /bin: Binários essenciais aos usuários e administradores do sistema. /sbin: Binários essenciais aos administradores do sistema mas nunca utilizados por usuários comuns.
Sistema de Arquivos Básico e Bibliotecas * Aparente redundância do sistema de arquivos: - Local de armazenamento depende do papel que o mesmo desempenha no sistema: /usr/bin: Binários não essenciais aos usuários e administradores do sistema. /usr/sbin: Binários não essenciais aos administradores do sistema. Mesma lógica é aplicada aos diretórios de armazenamento de bibliotecas: /lib e /usr/lib. - Uma vez criados todos os diretórios do sistema (listados anteriormente) é necessário considerar os componentes de SW.
Sistema de Arquivos Básico e Bibliotecas * Bibliotecas - Assim como o sistema de arquivos básico, existe também um conjunto mínimo de bibliotecas que um sistema Linux embarcado deve possuir. - glibc Principal pacote de bibliotecas do sistema. Bibliotecas normalmente localizadas em /lib/<target_prefix>/. Necessário avaliar quais serão as bibliotecas realmente necessárias no sistema alvo. Evitar desperdício de espaço e possivelmente memória principal na imagem final.
Sistema de Arquivos Básico e Bibliotecas * Bibliotecas - glibc
Sistema de Arquivos Básico e Bibliotecas * Bibliotecas - glibc
Sistema de Arquivos Básico e Bibliotecas * Bibliotecas - uclibc Assim como a glibc, é um pacote de bibliotecas. Nomes e modo de uso dos componentes da uclibc são análogos aos da glibc. Nem todas as bibliotecas que compõem a glibc estão disponíveis na uclibc. uclibc implementa somente: ld, libc, libcrypt, libdl, libm, libpthread, libresolv, e libutil. Bibliotecas normalmente localizadas em /lib/<target_prefix>/ uclibc/lib.
* Os principais componentes de um sistema embarcado Linux podem ser subdivididos em: - Bootloader; - Kernel Linux; - Aplicativos de usuário; - Toolchain (de forma mais abrangente). * Kernel Linux é composto internamente por vários módulos. * Componentes do kernel podem ser compilados built-in ou posteriormente acoplados ao mesmo.
* Módulos do kernel Linux - Módulos são códigos independentes que podem ser carregados/descarregados do kernel em tempo de execução. - Código escrito para módulos deve ter o mesmo cuidado que os códigos internos ao kernel. - Execução se dá no mesmo nível de permissão que o kernel. - Qualquer erro pode ocasionar a queda de todo o sistema. - Permitem extender funcionalidades do kernel sem necessidade de reiniciar o sistema.
* Módulos do kernel Linux - Considerações básicas Não executa como um programa qualquer, mas possui suas chamadas orientadas a eventos. Funções convencionais da glibc não são utilizadas, uma vez que o código do kernel deve ser independente. Funções como printf, malloc, etc, são substituídas por versões específicas para o kernel: printk kmalloc, etc. Necessita de pelo menos duas funções para existir: inicialização e finalização.
* Módulos do kernel Linux - Módulo Hello World-1 #include <linux/module.h> #include <linux/kernel.h> /* Funcao de inicializacao */ int init_module(void) { printk(kern_info "Hello world 1.\n"); return 0; } /* Funcao de finalizacao */ void cleanup_module(void) { printk(kern_info "Goodbye world 1.\n"); }
* Módulos do kernel Linux - Considerações básicas init_module() contém código a ser executado quando da inicialização do módulo. cleanup_module() contém código a ser executado quando da remoção do módulo do sistema. printk() perfaz mesma função do printf(). Entretanto, não tem o objetivo de informar algo ao usuário, mas sim para log do kernel.
* Módulos do kernel Linux - Compilação Módulos do kernel são compilados de forma diferente de aplicações de usuário. Compilações normalmente são feitas através de Makefiles. Para o kernel existe um modo de manutenção dos Makefiles chamado de kbuild. Mais informações sobre compilação de módulos podem ser encontradas no arquivo linux/documentation/kbuild/ modules.txt
* Módulos do kernel Linux - Compilação Makefile obj-m += hello-1.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
* Módulos do kernel Linux - Compilação Mais detalhes podem ser encontrados em linux/ Documentation/kbuild/makefiles.txt. - Instanciamento / Remoção $ insmod / rmmod / modprobe / lsmod $ modinfo
* Módulos do kernel Linux - Módulo Hello World-2 #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> static int hello2_data initdata = 3; static int init hello_2_init(void) { printk(kern_info "Hello, world 2\n"); return 0; } static void exit hello_2_exit(void) { printk(kern_info "Goodbye, world 2\n"); } module_init(hello_2_init); module_exit(hello_2_exit);
* Módulos do kernel Linux - Macros Macro init faz com que a função seja descarregada (e sua memória liberada) assim que a mesma termina - somente para módulos built-in. initdata funciona de maneira correlata, entretanto aplicado somente a variáveis e não a funções. Macro exit causa a omissão da função quando o módulo é compilado junto ao kernel - somente para módulos built-in.
* Módulos do kernel Linux - Metadados Módulos podem conter internamente informações sobre si mesmo. Existem macros específicas para a declaração de tais informações. Tipo de licença, autor, descrição e dispositivos suportados podem ser algumas das informações passíveis de serem adicionadas.
* Módulos do kernel Linux - Metadados #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #define MOD_AUTHOR "Vicente Amorim <vjpamorim@gmail.com>" #define MOD_DESC "Exemplo de um modulo do kernel" static int init hello_3_init(void) { printk(kern_info "Hello, world 3\n"); return 0; } static void exit hello_3_exit(void) { printk(kern_info "Goodbye, world 3\n"); } MODULE_LICENSE("GPL"); MODULE_AUTHOR(MOD_AUTHOR); MODULE_DESCRIPTION(MOD_DESC); MODULE_SUPPORTED_DEVICE("exemplo_modulo"); module_init(hello_3_init); module_exit(hello_3_exit);
* Módulos do kernel Linux - Módulos vs. Programas de usuário Um programa de usuário normalmente inicia pela rotina main(), executa um conjunto de instruções e termina. Um módulo sempre inicia pela rotina marcada com init_module ou através da função especificada na chamada module_init(). Função de inicialização diz ao kernel o que o módulo efetivamente faz. Após a função de inicialização o módulo não faz mais nada até que o kernel queira executar alguma função pertencente àquele módulo.
* Módulos do kernel Linux - Módulos vs. Programas de usuário Ao fazer uso de funções externas (printf() da libc, por exemplo), o código das mesmas só é integrado ao programa no estágio de link-edição. Módulos são arquivos objetos nos quais os símbolos (printk(), por exemplo) são resolvidos durante seu instanciamento ($ insmod). Códigos do kernel não dependem de biblioteca externa. Todas as definições de símbolos exportados pelo kernel podem ser encontradas em: /proc/kallsyms.
* Módulos do kernel Linux - Espaço de usuário vs. Espaço kernel Kernel é o gerente geral: Decide quem pode acessar determinados recursos e quando isso pode acontecer. Recursos em um sistema podem ser acessados através de diversos níveis: CPU 80386 possuía 4 modos de execução. Sistemas Unix-like utilizam somente o modo mais alto e mais baixo de execução (supervisor mode vs. user mode). Paradigma Funções vs. System Calls -> Espaço de usuário vs. espaço kernel.