Outra fonte interessante é o curso An introduction to Linux Kernel Programming.
obj-m += ofd.o
obj-y += ofd/
$ make -j 5 ARCH=i386
$ qemu-system-i386 -hda ../ArchLinux_mc504.cow -kernel arch/x86/boot/bzImage -append "rw root=/dev/hda" -drive format=raw,file=drivers/ofd/ofd.ko
$ cat /dev/hdb > ofd.ko $ insmod ofd.ko $ lsmod ... $ rmmod ofd.ko $ dmesg | grep ofd
Neste caso, você irá compilar os drivers e depois incorporá-los dinamicamente com o comando insmod ou modprobe. Utilize, preferencialmente, uma partição dedicada só para isso ou uma máquina virtual. Caso contrário, sua implementação pode corromper o kernel.
# dnf install kernel-develPara instalar headers que combinam com o kernel instalado.
# dnf install "kernel-devel-uname-r == $(uname -r)"
CC = gcc CONFIG_MODULE_SIG=n ifeq ($(KERNELRELEASE),) KERNELDIR ?= /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) .PHONY: build clean build: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules clean: rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c else $(info Building with KERNELRELEASE = ${KERNELRELEASE}) obj-m := ofd.o endif
$ insmod ofcd.ko $ lsmod ... $ dmesg | tail $ cat /proc/devices ... 252 ofcdÉ possível criar as entradas em /dev explicitamente:
$ mknod /dev/ofcd0 c 252 0 $ mknod /dev/ofcd1 c 252 1 $ mknod /dev/ofcd2 c 252 2 $ ls /devNo entanto, ainda não conseguimos utilizar estes arquivos.
$ cat /dev/ofcd0
$ insmod ofcd-null.ko $ ls /dev/ $ cat /dev/ofcd-null $ echo "teste" > /dev/ofcd-null
static char c; static ssize_t my_read(struct file *f, char __user *buf, size_t len, loff_t *off) { printk(KERN_INFO "Driver: read()\n"); buf[0] = c; return 1; } static ssize_t my_write(struct file *f, const char __user *buf, size_t len, loff_t *off) { printk(KERN_INFO "Driver: write()\n"); c = buf[len - 1]; return len; }Esta abordagem está codificada no arquivo ofcd-lastchar-bug.c. Você pode testar com a aplicação bug-app.
static char c; static ssize_t my_read(struct file *f, char __user *buf, size_t len, loff_t *off) { printk(KERN_INFO "Driver: read()\n"); if (copy_to_user(buf, &c, 1) != 0) return -EFAULT; else return 1; } static ssize_t my_write(struct file *f, const char __user *buf, size_t len, loff_t *off) { printk(KERN_INFO "Driver: write()\n"); if (copy_from_user(&c, buf + len - 1, 1) != 0) return -EFAULT; else return len; }Refaça os testes com a aplicação lastchar-app.
Se você procurar a documentação sobre copy_to_user e copy_from_user verá que estas funções podem dormir. Por quê?
Exercício simples (não é sugestão de tema para projeto): tente implementar uma versão deste driver que armazene a última escrita com kmalloc e kfree.
./query_app to display the driver variables ./query_app -c to clear the driver variables ./query_app -g to display the driver variables ./query_app -s to set the driver variablesVocê deve rodar este exemplo e entender o funcionamento de ioctl. Como posso alterar o tipo de argumento passado para ioctl? Esta função permite grande flexibilidade..
No capítulo 4 do Kernel Hacking: ioctls: Not writing a new system call podemos encontrar a seguinte informação:
A system call generally looks like this
asmlinkage long sys_mycall(int arg)
{
return 0;
}
First, in most cases you don't want to create a new system call. You
create a character device and implement an appropriate ioctl for
it. This is much more flexible than system calls, doesn't have to be
entered in every architecture's include/asm/unistd.h and
arch/kernel/entry.S file, and is much more likely to be accepted by
Linus.
No entanto, nem todos amam este design. Você consegue dizer algumas desvantagens?
Sistemas de arquivos podem ser implementados como módulo que podem ser adicionados dinamicamente ao kernel. Veja os seguintes exemplos:
$ dd if=/dev/zero of=rep bs=1k count=4 $ mkdir -p mnt $ mount -t lwnfs -o loop rep mnt $ cd mnt $ ls $ cat counter0 0 $ cat counter0 1 $ echo 200 > counter1 $ cat counter1 200
$ dd if=/dev/zero of=rep bs=1k count=4 $ mkdir -p mnt $ mount -t islenefs -o loop rep mnt
Apresentação obrigatória nos dias 12 ou 14 de dezembro. Entrega do código, uma abordagem para testes e um arquivo README explicando o projeto via Moodle.