diff --git a/README.md b/README.md index f4275c9..c87d09c 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,14 @@ After the first build, you can also run just: to save a few seconds. `./run` wouldn't rebuild everything, but checking timestamps takes a few moments. +If you are feeling fancy, you can also insert modules with: + + modprobe hello + +and if you are feeling raw, you can use: + + /myinsmod.out /hello.ko + We use `printk` a lot, and it shows on the QEMU terminal by default. If that annoys you (e.g. you want to see stdout separately), do: dmesg -n 1 @@ -299,6 +307,7 @@ But TODO I don't think you can see where you are in the kernel source code and l 1. [Introduction](introduction.md) 1. [Build](build.md) 1. [kmod](kmod.md) +1. [] 1. [Bibliography](bibliography.md) 1. Examples 1. [Host](host/) diff --git a/kernel_module/debugfs.c b/kernel_module/debugfs.c index 42ead41..2cd74b5 100644 --- a/kernel_module/debugfs.c +++ b/kernel_module/debugfs.c @@ -17,7 +17,7 @@ MODULE_LICENSE("GPL"); static struct dentry *dir; static u32 value = 42; -int init_module(void) +static int myinit(void) { struct dentry *file; dir = debugfs_create_dir("lkmc_debugfs", 0); @@ -33,7 +33,10 @@ int init_module(void) return 0; } -void cleanup_module(void) +static void myexit(void) { debugfs_remove_recursive(dir); } + +module_init(myinit) +module_exit(myexit) diff --git a/kernel_module/fops.c b/kernel_module/fops.c index c8ca1bc..216a08d 100644 --- a/kernel_module/fops.c +++ b/kernel_module/fops.c @@ -136,7 +136,7 @@ static const struct file_operations fops = { .write = fop_write, }; -int init_module(void) +static int myinit(void) { struct dentry *file; dir = debugfs_create_dir("lkmc_fops", 0); @@ -152,7 +152,10 @@ int init_module(void) return 0; } -void cleanup_module(void) +static void myexit(void) { debugfs_remove_recursive(dir); } + +module_init(myinit) +module_exit(myexit) diff --git a/kernel_module/hello.c b/kernel_module/hello.c index 7210935..1b65f24 100644 --- a/kernel_module/hello.c +++ b/kernel_module/hello.c @@ -5,7 +5,7 @@ Hello world module. insmod hello.ko dmesg -c | grep 'hello init' rmmod hello.ko - dmesg -c | grep 'hello cleanup' + dmesg -c | grep 'hello exit' */ #include @@ -13,13 +13,16 @@ Hello world module. MODULE_LICENSE("GPL"); -int init_module(void) +static int myinit(void) { printk(KERN_INFO "hello init\n"); return 0; } -void cleanup_module(void) +static void myexit(void) { - printk(KERN_INFO "hello cleanup\n"); + printk(KERN_INFO "hello exit\n"); } + +module_init(myinit) +module_exit(myexit) diff --git a/kernel_module/hello2.c b/kernel_module/hello2.c index 7beebbd..1fbbf43 100644 --- a/kernel_module/hello2.c +++ b/kernel_module/hello2.c @@ -9,13 +9,16 @@ Mostly to check that our build infrastructure can handle more than one module! MODULE_LICENSE("GPL"); -int init_module(void) +static int myinit(void) { printk(KERN_INFO "hello2 init\n"); return 0; } -void cleanup_module(void) +static void myexit(void) { - printk(KERN_INFO "hello2 cleanup\n"); + printk(KERN_INFO "hello2 exit\n"); } + +module_init(myinit) +module_exit(myexit) diff --git a/kernel_module/irq.c b/kernel_module/irq.c index 339509a..43dbe9c 100644 --- a/kernel_module/irq.c +++ b/kernel_module/irq.c @@ -23,7 +23,7 @@ static irqreturn_t handler(int i, void *v) return IRQ_HANDLED; } -int init_module(void) +static int myinit(void) { irqreturn_t r; r = request_irq( @@ -37,6 +37,9 @@ int init_module(void) return 0; } -void cleanup_module(void) +static void myexit(void) { } + +module_init(myinit) +module_exit(myexit) diff --git a/kernel_module/kthread.c b/kernel_module/kthread.c index 7e0d796..22a092f 100644 --- a/kernel_module/kthread.c +++ b/kernel_module/kthread.c @@ -31,15 +31,18 @@ static int work_func(void *data) return 0; } -int init_module(void) +static int myinit(void) { kthread = kthread_create(work_func, NULL, "mykthread"); wake_up_process(kthread); return 0; } -void cleanup_module(void) +static void myexit(void) { /* Waits for thread to return. */ kthread_stop(kthread); } + +module_init(myinit) +module_exit(myexit) diff --git a/kernel_module/kthreads.c b/kernel_module/kthreads.c index 0ede48a..690b342 100644 --- a/kernel_module/kthreads.c +++ b/kernel_module/kthreads.c @@ -37,7 +37,7 @@ static int work_func2(void *data) return 0; } -int init_module(void) +static int myinit(void) { kthread1 = kthread_create(work_func1, NULL, "mykthread1"); kthread2 = kthread_create(work_func2, NULL, "mykthread2"); @@ -46,8 +46,11 @@ int init_module(void) return 0; } -void cleanup_module(void) +static void myexit(void) { kthread_stop(kthread1); kthread_stop(kthread2); } + +module_init(myinit) +module_exit(myexit) diff --git a/kernel_module/module_init.c b/kernel_module/module_init.c index bae16d5..0f880ad 100644 --- a/kernel_module/module_init.c +++ b/kernel_module/module_init.c @@ -1,9 +1,13 @@ /* -Hello world with module_init / exit macros. +https://stackoverflow.com/questions/3218320/what-is-the-difference-between-module-init-and-init-module-in-a-linux-kernel-mod -TODO: vs direct init_module and cleanup_module. +Hello world with direct init_module and cleantup_module. -- modprobe only works with the macros. Try "modprobe module_init". +This appears to be an older method that still works but has some drawbacks. + +vs module_init and module_exit? + +- modprobe only works with the module_init / module_exit. Try "modprobe module_init". */ #include @@ -11,16 +15,13 @@ TODO: vs direct init_module and cleanup_module. MODULE_LICENSE("GPL"); -static int module_init_init(void) +int init_module(void) { - pr_info("module_init init\n"); + printk(KERN_INFO "init_module\n"); return 0; } -static void module_init_exit(void) +void cleanup_module(void) { - pr_info("module_exit cleanup\n"); + printk(KERN_INFO "cleanup_module\n"); } - -module_init(module_init_init) -module_exit(module_init_exit) diff --git a/kernel_module/panic.c b/kernel_module/panic.c index 8a0729c..a0f0ff9 100644 --- a/kernel_module/panic.c +++ b/kernel_module/panic.c @@ -13,14 +13,17 @@ The alternative is to get the serial data out streamed to console or to a file: #include #include -int init_module(void) +static int myinit(void) { printk(KERN_INFO "panic init\n"); panic("hello panic"); return 0; } -void cleanup_module(void) +static void myexit(void) { printk(KERN_INFO "panic cleanup\n"); } + +module_init(myinit) +module_exit(myexit) diff --git a/kernel_module/params.c b/kernel_module/params.c index 7738c80..0bfc914 100644 --- a/kernel_module/params.c +++ b/kernel_module/params.c @@ -47,14 +47,17 @@ static int work_func(void *data) return 0; } -int init_module(void) +static int myinit(void) { kthread = kthread_create(work_func, NULL, "mykthread"); wake_up_process(kthread); return 0; } -void cleanup_module(void) +static void myexit(void) { kthread_stop(kthread); } + +module_init(myinit) +module_exit(myexit) diff --git a/kernel_module/poll.c b/kernel_module/poll.c index c078fec..f7957cb 100644 --- a/kernel_module/poll.c +++ b/kernel_module/poll.c @@ -61,7 +61,7 @@ static const struct file_operations fops = { .poll = poll }; -int init_module(void) +static int myinit(void) { dir = debugfs_create_dir("lkmc_poll", 0); debugfs_create_file("f", 0666, dir, NULL, &fops); @@ -70,7 +70,10 @@ int init_module(void) return 0; } -void cleanup_module(void) +static void myexit(void) { debugfs_remove_recursive(dir); } + +module_init(myinit) +module_exit(myexit) diff --git a/kernel_module/schedule.c b/kernel_module/schedule.c index 14332f4..a4867aa 100644 --- a/kernel_module/schedule.c +++ b/kernel_module/schedule.c @@ -5,6 +5,8 @@ kthreads only allow interrupting if you call schedule. If you don't, they just run forever, and you have to kill the VM. +Sleep functions like usleep_range also end up calling schedule. + Test with: dmesg -n 1 @@ -19,7 +21,6 @@ Then: - yn=1: all good */ -#include /* usleep_range */ #include #include #include @@ -45,14 +46,17 @@ static int work_func(void *data) return 0; } -int init_module(void) +static int myinit(void) { kthread = kthread_create(work_func, NULL, "mykthread"); wake_up_process(kthread); return 0; } -void cleanup_module(void) +static void myexit(void) { kthread_stop(kthread); } + +module_init(myinit) +module_exit(myexit) diff --git a/kernel_module/sleep.c b/kernel_module/sleep.c index ef359a7..2fc2909 100644 --- a/kernel_module/sleep.c +++ b/kernel_module/sleep.c @@ -32,7 +32,7 @@ static void work_func(struct work_struct *work) } } -int init_module(void) +static int myinit(void) { DECLARE_WORK(work, work_func); queue = create_workqueue("myworkqueue"); @@ -40,8 +40,11 @@ int init_module(void) return 0; } -void cleanup_module(void) +static void myexit(void) { atomic_set(&run, 0); destroy_workqueue(queue); } + +module_init(myinit) +module_exit(myexit) diff --git a/kernel_module/timer.c b/kernel_module/timer.c index 15c46ae..2527967 100644 --- a/kernel_module/timer.c +++ b/kernel_module/timer.c @@ -28,14 +28,17 @@ static void callback(unsigned long data) mod_timer(&mytimer, jiffies + onesec); } -int init_module(void) +static int myinit(void) { onesec = msecs_to_jiffies(1000); mod_timer(&mytimer, jiffies + onesec); return 0; } -void cleanup_module(void) +static void myexit(void) { del_timer(&mytimer); } + +module_init(myinit) +module_exit(myexit) diff --git a/kernel_module/wait_queue.c b/kernel_module/wait_queue.c index b257457..c4a6108 100644 --- a/kernel_module/wait_queue.c +++ b/kernel_module/wait_queue.c @@ -46,7 +46,7 @@ static int kthread_func2(void *data) return 0; } -int init_module(void) +static int myinit(void) { init_waitqueue_head(&queue); kthread1 = kthread_create(kthread_func1, NULL, "mykthread1"); @@ -56,8 +56,11 @@ int init_module(void) return 0; } -void cleanup_module(void) +static void myexit(void) { kthread_stop(kthread1); kthread_stop(kthread2); } + +module_init(myinit) +module_exit(myexit) diff --git a/kernel_module/work_from_work.c b/kernel_module/work_from_work.c index f017da2..525ea91 100644 --- a/kernel_module/work_from_work.c +++ b/kernel_module/work_from_work.c @@ -21,7 +21,7 @@ static void work_func(struct work_struct *work) queue_delayed_work(queue, &next_work, HZ); } -int init_module(void) +static int myinit(void) { DECLARE_WORK(work, work_func); queue = create_workqueue("myworkqueue"); @@ -29,7 +29,10 @@ int init_module(void) return 0; } -void cleanup_module(void) +static void myexit(void) { destroy_workqueue(queue); } + +module_init(myinit) +module_exit(myexit) diff --git a/kernel_module/workqueue_cheat.c b/kernel_module/workqueue_cheat.c index 59f8f06..ab6e32d 100644 --- a/kernel_module/workqueue_cheat.c +++ b/kernel_module/workqueue_cheat.c @@ -32,15 +32,18 @@ static void work_func(struct work_struct *work) DECLARE_WORK(work, work_func); -int init_module(void) +static int myinit(void) { queue = create_singlethread_workqueue("myworkqueue"); queue_work(queue, &work); return 0; } -void cleanup_module(void) +static void myexit(void) { /* Waits for jobs to finish. */ destroy_workqueue(queue); } + +module_init(myinit) +module_exit(myexit) diff --git a/kmod.md b/kmod.md index b719cc8..234ec25 100644 --- a/kmod.md +++ b/kmod.md @@ -1,6 +1,10 @@ # kmod -Implements `lsmod`, `insmod`, `rmmod`, and other tools. +Multi-call executable that implements: `lsmod`, `insmod`, `rmmod`, and other tools. + +BusyBox also implements its own version of those executables. + +Source: The other tools are just symlinks to it. @@ -77,7 +81,12 @@ Remove a module. Takes either the module name or the `.ko` file: ## modprobe -List available modules relative path to `/lib/modules/VERSION/`: +Vs `insmod`: + +- +- + +List available modules relative path to `/lib/modules/$KERNEL_VERSION/`: sudo modprobe -l