???????????????????????????????????????е???????????????????????????????????????????????????????????????dmesg??????????KERN_INFO??????????????ж??????__init??__exit?????? —— ??????????????????????????????????????????C?????????????????????????????顣???б???__init???????????????????????????????????????????????“Freeing unused kernel memory…[???δ??????????……]”?????????__exit????????????????????????????ú????????????????????????????β????module_init()??module_exit()????????reverse_init()??reverse_exit()???????ó????????????????????????????????????????????????????????init()??exit()??????start()??stop()??????????????ɡ?????????????????????????????????????????????е??κκ?????????????????????????????????????????????У??????????????????????????????
??????Щ????Щ???????? – ???????????????????????ɡ???????????????????????
????# modprobe foo bar=1
????modinfo???????????????????в?????????Щ???????/sys/module//parameters??????????á????????????????????????洢???? —— ??????????С?????????????á???MODULE_DESCRIPTION()????????????У?
????static unsigned long buffer_size = 8192;
????module_param(buffer_size?? ulong?? (S_IRUSR | S_IRGRP | S_IROTH));
????MODULE_PARM_DESC(buffer_size?? "Internal buffer size");
????????????????????????????洢????????????????????????sysfs?????????????????????????????????У???????modinfo??????С?
??????????????????????buffer_size???????????reverse_init()???????Ч????????ü????????????????? —— ???????????????????????????????????????С?
????static int __init reverse_init()
????{
????if (!buffer_size)
????return -1;
????printk(KERN_INFO
????"reverse device has been registered?? buffer size is %lu bytes "??
????buffer_size);
????return 0;
????}
??????????????????????0???????ζ????????????
????????
????????????????Linux?????????????е??????????????????????????????????????????????????????????????????????????????????????ü??????????Cscope —— ??????????е??????????????????????????????????????????????make cscope && cscope??Cscope??Vim???Emacs????ú????????????????????????????????
??????????????????????????????????http://lxr.free-electrons.com?ɡ????????????web??????????????????????????Cscope????????磬??????????????????÷???????????????????????????????
???????????????????????????????????????е????汾??????linux-headers???????????????????build-essential?????????????????????????????????????Makefile??壺
????obj-m += reverse.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
?????????????make???????????????顣????????????????????????????reverse.ko????????sudo insmod reverse.ko?????????飬???????????????
????$ dmesg | tail -1
????[ 5905.042081] reverse device has been registered?? buffer size is 8192 bytes
?????????????????????л?????????? —— ??????豸????????????????????
?????????豸
??????Linux?У???????????????豸?????????“?????豸”?????????“misc”???????????????????С???豸??????????????????????????????????л????豸???????????豸???10??????????????(drivers/char/misc.c????????????????豸???????Щ?豸????豸??????????????????????????????????????豸??
?????????豸?????????豸?????????????????????????struct misc_device????????????Σ???????????????????y???????????????????misc_register()????????????????linux/miscdevice.h??????
????static struct miscdevice reverse_misc_device = {
????.minor = MISC_DYNAMIC_MINOR??
????.name = "reverse"??
????.fops = &reverse_fops
????};
????static int __init reverse_init()
????{
????...
????misc_register(&reverse_misc_device);
????printk(KERN_INFO ...
????}
?????????????????“reverse”???豸???????????????????????????豸???????????????????????????????????????????ж?o????????豸??
????static void __exit reverse_exit(void)
????{
????misc_deregister(&reverse_misc_device);
????...
????}
????‘fops’??δ洢??????????????file_operations??????Linux/fs.h??????????????????????????????reverse_fops???????£?
????static struct file_operations reverse_fops = {
????.owner = THIS_MODULE??
????.open = reverse_open??
????...
????.llseek = noop_llseek
????};
????????reverse_fops?????????л?????????????????????????????????????豸????д??????????????????????С?????????????Щ?????????????????????????????????????????????llseek?????noop_llseek()??????????壩?????????ɡ???????????????????????????????????????????????豸?????????????????????????????
?????????
???????????????÷????????????????????????????????????μ???????????????????????????????????????????????????ó???й?????????????????????????????RAM???????????????á???????????У????????????Щ????????????????У??????????????
???????????????????????????????????????????????????????????б?????????????????????????????????????????????????????????????“struct buffer”??
????struct buffer {
????char *data?? *end?? *read_ptr;
????unsigned long size;
????};
????data?????????洢????????????????????end??????????β???????????read_ptr??read()???????????????????????size???????????????洢?? —— ????????????????????????????????????????????????????????Щ?????????????????з??????????????????????????????buffer_alloc()??buffer_free()??
????static struct buffer buffer_alloc(unsigned long size) { struct buffer *buf; buf = kzalloc(sizeof(buf)?? GFP_KERNEL); if (unlikely(!buf)) goto out; … out: return buf; }
?????????????kmalloc()???????????kfree()??????kzalloc()???????????????????????????malloc()??????????????????????????????????????????????????????GFP_KERNEL???????????????????????棨??????DMA?????????У????????????????????????????μ?????????sizeof(*buf)????????????????????????????????????????С??
???????????????kmalloc()????????????NULL???????????????????????unlikely()?????á?????????????likely()??????????????У?????????????????????????????????????????????????????????????????????????????????????????
?????????goto????????????????а?????????Linux????????Щ????????????????????????????????????????????????????????????????????????????????????????е?try-catch???顣
????????buffer_alloc()??buffer_free()??open??close??????ú?????
????static int reverse_open(struct inode *inode?? struct file *file)
????{
????int err = 0;
????file->private_data = buffer_alloc(buffer_size);
????...
????return err;
????}
????struct file????????????????????????洢???????????????統(tǒng)????λ???file->f_pos)?????(file->f_flags?????????????file->f_mode)?????????????file->privatedata?????????????Щ??????????????????void *????????????????????????????????????????????????洢??????
????????????????????????????????????-ENOMEM???????????????????????????C???е????open(2)??????(??glibc)????????????????????errno ??
????????ζ???д
????“read”??“write”????????????????????????????д???????????????????????????????洢????Σ???????κ?????洢??read?????????????????????????????????????????????????????????revers_eread()??????????????????У?read()????????п??????????????????????У????????????????????????????????????????????‘wait queues’??
???????????????????????????????????????????????struct task_struct?洢‘current’????????????????У?????У???????????????????С????schedule()???????????????????????С?????????????????????н??????????TASK_RUNNING????????????????????????????????????????????Linux?ж??????????????????????TASK_INTERRUPTIBLE????????????????ж????????TASK_KILLABLE?????????????????е?????????????Щ?????????????????????????????Щ???
???????????洢??????????????????????????????????????????wait_queue_headt readqueue??ο?????????e???linux/sched.h?????????????DECLARE_WAITQUEUE()????????????????????С????????????£???????????????????????????е?buffer_alloc()??
????init_waitqueue_head(&buf->read_queue);
?????????????????????????read_ptr != end????????????????????????????????ж???磬???Ctrl+C????????“read”??????????????????
static ssize_t reverse_read(struct file *file?? char __user * out??
size_t size?? loff_t * off)
{
struct buffer *buf = file->private_data;
ssize_t result;
while (buf->read_ptr == buf->end) {
if (file->f_flags & O_NONBLOCK) {
result = -EAGAIN;
goto out;
}
if (wait_event_interruptible
(buf->read_queue?? buf->read_ptr != buf->end)) {
result = -ERESTARTSYS;
goto out;
}
}
...
?????????????????????п???????????????????wait_event_interruptible()?????????????????????????????????????????д????????????e?????wait_event_interruptible()???ж?????????????0???????????-ERESTARTSYS????δ?????ζ????????????????????file->f_flags??????????????????????????????????????-EAGAIN??