No arquivo newdrivers.tar.xz você encontrará os arquivos referentes aos drivers deste experimento. No arquivo apps.tar.xz você encontrará um diretório com arquivos de teste para os drivers. Para cada arquivo .c há um executável gerado para arquitetura 386. Caso queira gerar novo executável utilize o site ccplusplus.
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 as aplicações teste-lastchar e teste-lastchar-invalid-buffer.
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 teste-lastchar e teste-lastchar-invalid-buffer com o driver ofcd-lastchar.
Se você procurar a documentação sobre copy_to_user e copy_from_user verá que estas funções podem dormir. Por quê?
Sugestão: 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?