RSS

Uma humilde visão de Kernel,syscalls e módulos.

27 dez

Não sou conhecedor de tudo que o sistema Linux tem , mesmo por que
uso a pouco tempo , mas vou tentar explanar alguns conceitos básicos,
dos quais me deparei no decorrer dos anos.

Kernel do Linux é um programa bem complexo escrito na linguagem “ansi C“,
com algumas partes específicas de cada arquitetura de computador utilizando
assembly“, sua missão é fazer o elo entre software e hardware. Quem já compilou
o kernel já teve o privilégio de ver uma tela com “ncurses” com uma das opções
“loadable Module”, se você ativar, poderá ativar e desativar drivers e funções,
maioria dos sistemas linux já vem com esta opção ativada , Estes módulos são
partes do “kernel” que possibilitam serem incorporados e removidos,sem a
reinicialização do sistema.

caso queira ver o código do kernel do linux
baixe o AQUI

Syscalls é um ponto de entrada para o kernel Linux, são chamadas indiretas
a maioria das chamadas de sistema têm correspondentes funções da biblioteca
C , um wrapper que executar os passos necessários (por exemplo, prendendo ao modo
kernel). Assim fazendo uma chamada de sistema é o mesmo que chamar uma função
de biblioteca normal.

tabkernel

antes de partir para o rock n roll, vamos entender o básico de inline ASM
__asm__("" : saida : entrada : modificador);

exemplo adição simples com “ADD”

#include <stdio.h>
#include <unistd.h>
 
int main()
{
  int data1 = 8,data2 = 3;
 
  __asm__("addl  %%ebx,%%eax":"=a"(data1):"a"(data1), "b"(data2));
  fprintf(stdout, "data1 + data2 = %d\n", data1);
 
  return 0;
}

Vamos analisar como um código em linguagem C ,interrupção para um syscall
no caso o write() , veja a tabela aqui

 int write(int fd,const char * buf,unsigned int count)
    {
        long __res;
        asm("int $0x80"
            : "=a" (__res)
            : "0" (__NR_write), "b" ((long)fd),
              "c" ((long)buf), "d" ((long)count));
        if ((unsigned long)__res >= (unsigned long)-129) {
            errno = -__res;
            __res = -1;
        }
        return (int) __res;
    }

de onde veio o “__NR_write” ?

$cat unistd_32.h | grep write
#define __NR_write 4

algo equivalente a

  write:
         pushl %ebx              ; adiciona ebx na pilha
         movl 8(%esp), %ebx      ; adiciona primeiro argumento em ebx
         movl 12(%esp), %ecx     ; adiciona segundo argumento ecx
         movl 16(%esp), %edx     ; adiciona terceiro argumento edx
         movl $4, %eax           ; adiciona _ _NR_write em eax
         int  $0x80              ; interrupção para syscall
         cmpl $-125, %eax        ; checa o retorno 
         jbe .PULA               ; se nenhum erro JUMP para PULA
         negl %eax               ; complementa valor em eax
         movl %eax, errno        ; adiciona resultado em errno
         movl $-1, %eax          ; seta eax para -1
  .PULA: popl %ebx               ; tira ebx da pilha
         ret                     ; returna chamando programa

Em caso de erro, a maioria das chamadas do sistema retornam um número
negativo erro (ou seja, o valor negado de uma das constantes descritas
na errno (3)). O wrapper da biblioteca C esconde esse detalhe do chamador,
quando uma chamada de sistema retorna um valor negativo, o wrapper
copia o valor absoluto na variável errno, e retorna -1 como o valor de
retorno do wrapper.

O valor retornado por uma chamada de sistema bem sucedida, varia da chamada,
mais detalhes estão descritos no manual de páginas individuais. GNU C Library (glibc)
fornece a interface de syscall que se conecta ao kernel e fornece o mecanismo
para transição entre o aplicativo de espaço de usuário e o kernel.

mais informações
$ man syscall
$ man libc

Voltando para módulos de kernel

Qual é a vantagem de trabalhar com módulos do kernel ?

Bom você não precisa reiniciar seu sistema operacional toda vez que quiser
testar um driver, fora a transparência em que o linux faz isso, ajuda na
otimização do mesmo.
Vamos na prática

Arquivo que contém o módulo é um “arquivo objeto”, bem como um programa
gerado com GCC para depois compilar,utilizando oa argumento “-c”(compile only),
eles contêm símbolos para ajudar o kernel no percurso de carregamento de registro,
em suma passam pelo filesystem onde esta como “arquivo objeto” para memória RAM na
parte destinada de programas sendo carregados por um syscall, no endereço correto
reservada ao kernel.

vamos fazer nosso primeiro módulo

Makefile:

KDIR := /lib/modules/$(shell uname -r)/build

# Objeto
obj-m = macacos.o

# Regra default do Makefile
default:
        $(MAKE) -C $(KDIR) M=$(PWD) modules
        @rm -rf *.mod* Module.symvers *.o *~ *.markers *.order

# Limpando objetos e afins
clean:
        @rm -rf *~ *.o *.ko

arquivo macacos.c

#include <linux/module.h>

int init_module(void)
{
 printk("macacos me mordam \n");
 return 0;
}

void cleanup_module(void)
{
 printk("saindo\n");
}

MODULE_AUTHOR("Cooler_ ");
MODULE_DESCRIPTION("Just another test");
MODULE_LICENSE("BSD");

Passamos alguns comandos para compilar e instalar nosso módulo
e um comando para conferir se o módulo foi inserido…

$ make; insmod macacos.ko; dmesg | grep macacos
[17205.255807] macacos me mordam

Para remover o módulo
$ rmmod macacos

Olhe que interessante analisando o arquivo “.ko” com comando “strings”
$ strings macacos.ko
macacos me mordam
saindo
srcversion=F9191437D66715B7ADCB1E5
depends=
vermagic=3.0.0-14-generic SMP mod_unload modversions 686
module_layout
Pprintk
mcount
macacos

Bom o “insmod” usamos para instalar módulos e o “rmmod” para remover
como foi mostrado no exemplo, além deles temos o “lsmod” para listar módulos
exemplo

$ lsmod | grep snd
snd_hda_codec_hdmi     31426  1 
snd_hda_codec_realtek   254125  1 
snd_hda_intel          24262  6 
   |                      |    \_referências de outros módulos...
   |_ Nome Modulo         |_memória usada pelo módulo

modinfo” para se obter informações do módulo
$ modinfo snd_pcm
filename: /lib/modules/3.0.0-14-generic/kernel/sound/core/snd-pcm.ko
license: GPL
description: Midlevel PCM code for ALSA.
author: Jaroslav Kysela , Abramo Bagnara
srcversion: B1C966040673ADEA6AD0FAA
depends: snd,snd-page-alloc,snd-timer
vermagic: 3.0.0-14-generic SMP mod_unload modversions 686
parm: preallocate_dma:Preallocate DMA memory when the PCM devices are initialized. (int)
parm: maximum_substreams:Maximum substreams with preallocated DMA memory. (int)

Isso foi uma breve introdução…

Anúncios
 
1 comentário

Publicado por em dezembro 27, 2011 em Linguagem C, Linux

 

Tags:

Uma resposta para “Uma humilde visão de Kernel,syscalls e módulos.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

 
%d blogueiros gostam disto: