# Dados gerais
## Autoria

    Marcos André Oliveira - Matr. 060207 ( marcosandre19@gmail.com )
    Murilo A. Vasconcelos - Matr. 094816 ( muriloufg@gmail.com )
    Paulo Cezar P. Costa - Matr. 080153 ( paulocezar.ufg@gmail.com )
    Vinicius Vieira Pessoni - Matr. 080160 ( viniciuspessoni@gmail.com )

## Licenciamento

GPL

## Créditos
# Objetivo e descrição

    Debug via Impressão ( printk )
Depurar o kernel não é algo tão complicado. Na verdade pode ser uma tarefa simples, que exige o domínio de técnicas simples, e um bocado de paciência e perseverança.
Uma das técnicas mais comuns e simples de depurar o que está acontecendo com a aplicação é atravez
de impressões em pontos estratégicos do código e o mesmo pode ser feito quando queremos debugar o
código do kernel, o que é possível graças à função printk.
A função printk é, em espaço de núcleo, equivalente a função printf disponível apenas no espaço de usuário. Apesar de bastante semelhante à função printf, printk tem algumas diferenças, entre elas a possibilidade classificar as mensagem de acordo com sua gravidade associando diferentes níveis e prioridades as mensagens. Tal diferenciação é feita com o uso de macros que estão definidas no arquivo de cabeçalho "linux/kernel.h".
Tais macros são:
    KERN_EMERG - Indicando uma mensagem de emergência.
    KERN_ALERT - Indicando uma situção que necessita de ação imediata.
    KERN_CRIT - Aponta uma condição crítica, geralmente relacionada a falhas graves de hardware ou software.
    KERN_ERR - Indica que algum erro ocorreu, geralmente drivers comunicam falhas de hardware atravéz dessa macro.
    KERN_WARNING - Usada para reportar situações problemáticas que não prejudicam muito o sistema.
    KERN_NOTICE - Geralmente para situações que, apesar de normais, merecem atenção.
    KERN_INFO - Mensagens meramente informativas, indicando o estado do hardware ou de variáveis.
    KERN_DEBUG - Mensagens de debug para rastrear em que ponto do codigo a aplicação se encontra.
O printk é utilizado da seguinte maneira:
    printk( MACRO "MENSAGEM" <, variaveis > );
em tempo de compilação a macro é convertida para uma string de mensagem e incorporada à mensagem que será impressa.

# Código-fonte

flash.c
* * flash.c - Blink keyboard leds until the module is unloaded.
* #include <linux/module.h>
* #include <linux/init.h>
* #include <linux/tty.h> /* For fg_console, MAX_NR_CONSOLES */
* #include <linux/kd.h> /* For KDSETLED */
* #include <linux/vt.h>
* #include <linux/console_struct.h> /* For vc_cons */
* MODULE_DESCRIPTION("Example module illustrating the use of Keyboard LEDs.");
* MODULE_AUTHOR("Daniele Paolo Scarpazza");
* MODULE_LICENSE("GPL");
* extern int fg_console;
* struct timer_list my_timer;
* struct tty_driver *my_driver;
* char kbledstatus = 0;
* #define BLINK_DELAY HZ/5
* #define ALL_LEDS_ON 0x07
* #define RESTORE_LEDS 0xFF
* static void my_timer_func(unsigned long ptr)
* int *pstatus = (int *)ptr;
* if (*pstatus == ALL_LEDS_ON)
* #ifdef MODULE_DEBUG
* printk( KERN_NOTICE "Todos os leds estao acesos!\n");
* #endif
* *pstatus = RESTORE_LEDS;
* else
* *pstatus = ALL_LEDS_ON;
* ((my_driver->ops)->ioctl) (vc_cons[fg_console].d->vc_tty, NULL, KDSETLED, *pstatus);
* my_timer.expires = jiffies + BLINK_DELAY;
* add_timer(&my_timer);
* static int __init kbleds_init(void)
* int i;
* #ifdef MODULE_DEBUG
* printk(KERN_INFO "Iniciando o modulo em modo de DEBUG\n");
* #endif
* printk(KERN_INFO "kbleds: loading\n");
* printk(KERN_INFO "kbleds: fgconsole is %x\n", fg_console);
* for (i = 0; i < MAX_NR_CONSOLES; i++)
* if (!vc_cons[i].d) break;
* printk(KERN_INFO "poet_atkm: console[%i/%i] #%i, tty %lx\n", i,
* MAX_NR_CONSOLES, vc_cons[i].d->vc_num,
* (unsigned long)vc_cons[i].d->vc_tty);
* printk(KERN_INFO "kbleds: finished scanning consoles\n");
* my_driver = vc_cons[fg_console].d->vc_tty->driver;
* printk(KERN_INFO "kbleds: tty driver magic %x\n", my_driver->magic);
* #ifdef MODULE_DEBUG
* printk( KERN_NOTICE "Criando timer..\n");
* #endif
* init_timer(&my_timer);
* #ifdef MODULE_DEBUG
* printk( KERN_NOTICE "Timer criado.\n");
* #endif
* my_timer.function = my_timer_func;
* my_timer.data = (unsigned long)&kbledstatus;
* my_timer.expires = jiffies + BLINK_DELAY;
* add_timer(&my_timer);
* #ifdef MODULE_DEBUG
* printk( KERN_NOTICE "Modulo Inicializado com sucesso!\n");
* #endif
* return 0;
* static void __exit kbleds_cleanup(void)
* printk(KERN_INFO "kbleds: unloading...\n");
* #ifdef MODULE_DEBUG
* printk(KERN_INFO "Finalizando o modulo...\n");
* #endif
* del_timer(&my_timer);
* #ifdef MODULE_DEBUG
* printk( KERN_NOTICE "Timer deletado.\n");
* #endif
* ((my_driver->ops)->ioctl) (vc_cons[fg_console].d->vc_tty, NULL, KDSETLED,
* RESTORE_LEDS);
* module_init(kbleds_init);
* module_exit(kbleds_cleanup);

# Procedimentos para testes

Para testar o basta executar o comando make usando o Makefile abaixo
alterando o valor da variável DEBUG para qualquer coisa diferente de y as mensagens
de debug são desativadas.
Makefile
* KER_DIR := /lib/modules/$(shell uname -r)/build
* DEBUG = y
* obj-m = flash.o
* ifeq ($(DEBUG),y)
* DEBFLAGS = -O -g -DMODULE_DEBUG
* else
* DEBFLAHS = -O2
* endif
* EXTRA_CFLAGS += $(DEBFLAGS)
* all:
* $(MAKE) -C $(KER_DIR) M=$(PWD) modules
* @rm -rf *.mod* Module.symvers *.o *~ *.makers *.order
* clean:
* @rm -rf *~ *.o *.ko

# Considerações finais

Inicialmente tivemos várias dúvidas sobre o que deveria ser feito no trabalho, o que acreditamos ter sido o principal empecilho para que fosse produzido um material com mais qualidade. Quando nos demos conta do que deveria ser feito o tempo já estava curto, e o trabalho pode ter acabado ficando meio simplista.
Escolhemos fazer o debug usando printk, uma forma bem simples e poderosa de depurar o código, não tanto por suas características, mas pelo menos para a maioria do grupo, devido ao fato que estamos acostumados a depurar nossos algoritmos dessa forma.
A principal dificuldade foi controlar quando as mensagens devem ou não aparecer. Fizemos isso definindo uma variável que deve ser ativada ou desativada no Makefile, porém
a intenção era definir um alvo, "debug", assim quando fosse executado "make debug", o módulo seria
compilado para executar em modo debug, e quando o comando fosse apenas "make" a execução ocorreria
normalmente.

# Referências

[1] Linux Device Drivers 3rd Edition [2] The Linux Kernel Module Programming Guide [3] Linux Kernel Documentation