Use module_init, mention modprobe on readme

This commit is contained in:
Ciro Santilli
2017-06-06 08:08:31 +01:00
parent 7f9807ce45
commit 9337ea98d8
19 changed files with 116 additions and 48 deletions

View File

@@ -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. 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: 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 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. [Introduction](introduction.md)
1. [Build](build.md) 1. [Build](build.md)
1. [kmod](kmod.md) 1. [kmod](kmod.md)
1. []
1. [Bibliography](bibliography.md) 1. [Bibliography](bibliography.md)
1. Examples 1. Examples
1. [Host](host/) 1. [Host](host/)

View File

@@ -17,7 +17,7 @@ MODULE_LICENSE("GPL");
static struct dentry *dir; static struct dentry *dir;
static u32 value = 42; static u32 value = 42;
int init_module(void) static int myinit(void)
{ {
struct dentry *file; struct dentry *file;
dir = debugfs_create_dir("lkmc_debugfs", 0); dir = debugfs_create_dir("lkmc_debugfs", 0);
@@ -33,7 +33,10 @@ int init_module(void)
return 0; return 0;
} }
void cleanup_module(void) static void myexit(void)
{ {
debugfs_remove_recursive(dir); debugfs_remove_recursive(dir);
} }
module_init(myinit)
module_exit(myexit)

View File

@@ -136,7 +136,7 @@ static const struct file_operations fops = {
.write = fop_write, .write = fop_write,
}; };
int init_module(void) static int myinit(void)
{ {
struct dentry *file; struct dentry *file;
dir = debugfs_create_dir("lkmc_fops", 0); dir = debugfs_create_dir("lkmc_fops", 0);
@@ -152,7 +152,10 @@ int init_module(void)
return 0; return 0;
} }
void cleanup_module(void) static void myexit(void)
{ {
debugfs_remove_recursive(dir); debugfs_remove_recursive(dir);
} }
module_init(myinit)
module_exit(myexit)

View File

@@ -5,7 +5,7 @@ Hello world module.
insmod hello.ko insmod hello.ko
dmesg -c | grep 'hello init' dmesg -c | grep 'hello init'
rmmod hello.ko rmmod hello.ko
dmesg -c | grep 'hello cleanup' dmesg -c | grep 'hello exit'
*/ */
#include <linux/module.h> #include <linux/module.h>
@@ -13,13 +13,16 @@ Hello world module.
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
int init_module(void) static int myinit(void)
{ {
printk(KERN_INFO "hello init\n"); printk(KERN_INFO "hello init\n");
return 0; 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)

View File

@@ -9,13 +9,16 @@ Mostly to check that our build infrastructure can handle more than one module!
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
int init_module(void) static int myinit(void)
{ {
printk(KERN_INFO "hello2 init\n"); printk(KERN_INFO "hello2 init\n");
return 0; 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)

View File

@@ -23,7 +23,7 @@ static irqreturn_t handler(int i, void *v)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
int init_module(void) static int myinit(void)
{ {
irqreturn_t r; irqreturn_t r;
r = request_irq( r = request_irq(
@@ -37,6 +37,9 @@ int init_module(void)
return 0; return 0;
} }
void cleanup_module(void) static void myexit(void)
{ {
} }
module_init(myinit)
module_exit(myexit)

View File

@@ -31,15 +31,18 @@ static int work_func(void *data)
return 0; return 0;
} }
int init_module(void) static int myinit(void)
{ {
kthread = kthread_create(work_func, NULL, "mykthread"); kthread = kthread_create(work_func, NULL, "mykthread");
wake_up_process(kthread); wake_up_process(kthread);
return 0; return 0;
} }
void cleanup_module(void) static void myexit(void)
{ {
/* Waits for thread to return. */ /* Waits for thread to return. */
kthread_stop(kthread); kthread_stop(kthread);
} }
module_init(myinit)
module_exit(myexit)

View File

@@ -37,7 +37,7 @@ static int work_func2(void *data)
return 0; return 0;
} }
int init_module(void) static int myinit(void)
{ {
kthread1 = kthread_create(work_func1, NULL, "mykthread1"); kthread1 = kthread_create(work_func1, NULL, "mykthread1");
kthread2 = kthread_create(work_func2, NULL, "mykthread2"); kthread2 = kthread_create(work_func2, NULL, "mykthread2");
@@ -46,8 +46,11 @@ int init_module(void)
return 0; return 0;
} }
void cleanup_module(void) static void myexit(void)
{ {
kthread_stop(kthread1); kthread_stop(kthread1);
kthread_stop(kthread2); kthread_stop(kthread2);
} }
module_init(myinit)
module_exit(myexit)

View File

@@ -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 <linux/module.h> #include <linux/module.h>
@@ -11,16 +15,13 @@ TODO: vs direct init_module and cleanup_module.
MODULE_LICENSE("GPL"); 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; 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)

View File

@@ -13,14 +13,17 @@ The alternative is to get the serial data out streamed to console or to a file:
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
int init_module(void) static int myinit(void)
{ {
printk(KERN_INFO "panic init\n"); printk(KERN_INFO "panic init\n");
panic("hello panic"); panic("hello panic");
return 0; return 0;
} }
void cleanup_module(void) static void myexit(void)
{ {
printk(KERN_INFO "panic cleanup\n"); printk(KERN_INFO "panic cleanup\n");
} }
module_init(myinit)
module_exit(myexit)

View File

@@ -47,14 +47,17 @@ static int work_func(void *data)
return 0; return 0;
} }
int init_module(void) static int myinit(void)
{ {
kthread = kthread_create(work_func, NULL, "mykthread"); kthread = kthread_create(work_func, NULL, "mykthread");
wake_up_process(kthread); wake_up_process(kthread);
return 0; return 0;
} }
void cleanup_module(void) static void myexit(void)
{ {
kthread_stop(kthread); kthread_stop(kthread);
} }
module_init(myinit)
module_exit(myexit)

View File

@@ -61,7 +61,7 @@ static const struct file_operations fops = {
.poll = poll .poll = poll
}; };
int init_module(void) static int myinit(void)
{ {
dir = debugfs_create_dir("lkmc_poll", 0); dir = debugfs_create_dir("lkmc_poll", 0);
debugfs_create_file("f", 0666, dir, NULL, &fops); debugfs_create_file("f", 0666, dir, NULL, &fops);
@@ -70,7 +70,10 @@ int init_module(void)
return 0; return 0;
} }
void cleanup_module(void) static void myexit(void)
{ {
debugfs_remove_recursive(dir); debugfs_remove_recursive(dir);
} }
module_init(myinit)
module_exit(myexit)

View File

@@ -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. 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: Test with:
dmesg -n 1 dmesg -n 1
@@ -19,7 +21,6 @@ Then:
- yn=1: all good - yn=1: all good
*/ */
#include <linux/delay.h> /* usleep_range */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/module.h> #include <linux/module.h>
@@ -45,14 +46,17 @@ static int work_func(void *data)
return 0; return 0;
} }
int init_module(void) static int myinit(void)
{ {
kthread = kthread_create(work_func, NULL, "mykthread"); kthread = kthread_create(work_func, NULL, "mykthread");
wake_up_process(kthread); wake_up_process(kthread);
return 0; return 0;
} }
void cleanup_module(void) static void myexit(void)
{ {
kthread_stop(kthread); kthread_stop(kthread);
} }
module_init(myinit)
module_exit(myexit)

View File

@@ -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); DECLARE_WORK(work, work_func);
queue = create_workqueue("myworkqueue"); queue = create_workqueue("myworkqueue");
@@ -40,8 +40,11 @@ int init_module(void)
return 0; return 0;
} }
void cleanup_module(void) static void myexit(void)
{ {
atomic_set(&run, 0); atomic_set(&run, 0);
destroy_workqueue(queue); destroy_workqueue(queue);
} }
module_init(myinit)
module_exit(myexit)

View File

@@ -28,14 +28,17 @@ static void callback(unsigned long data)
mod_timer(&mytimer, jiffies + onesec); mod_timer(&mytimer, jiffies + onesec);
} }
int init_module(void) static int myinit(void)
{ {
onesec = msecs_to_jiffies(1000); onesec = msecs_to_jiffies(1000);
mod_timer(&mytimer, jiffies + onesec); mod_timer(&mytimer, jiffies + onesec);
return 0; return 0;
} }
void cleanup_module(void) static void myexit(void)
{ {
del_timer(&mytimer); del_timer(&mytimer);
} }
module_init(myinit)
module_exit(myexit)

View File

@@ -46,7 +46,7 @@ static int kthread_func2(void *data)
return 0; return 0;
} }
int init_module(void) static int myinit(void)
{ {
init_waitqueue_head(&queue); init_waitqueue_head(&queue);
kthread1 = kthread_create(kthread_func1, NULL, "mykthread1"); kthread1 = kthread_create(kthread_func1, NULL, "mykthread1");
@@ -56,8 +56,11 @@ int init_module(void)
return 0; return 0;
} }
void cleanup_module(void) static void myexit(void)
{ {
kthread_stop(kthread1); kthread_stop(kthread1);
kthread_stop(kthread2); kthread_stop(kthread2);
} }
module_init(myinit)
module_exit(myexit)

View File

@@ -21,7 +21,7 @@ static void work_func(struct work_struct *work)
queue_delayed_work(queue, &next_work, HZ); queue_delayed_work(queue, &next_work, HZ);
} }
int init_module(void) static int myinit(void)
{ {
DECLARE_WORK(work, work_func); DECLARE_WORK(work, work_func);
queue = create_workqueue("myworkqueue"); queue = create_workqueue("myworkqueue");
@@ -29,7 +29,10 @@ int init_module(void)
return 0; return 0;
} }
void cleanup_module(void) static void myexit(void)
{ {
destroy_workqueue(queue); destroy_workqueue(queue);
} }
module_init(myinit)
module_exit(myexit)

View File

@@ -32,15 +32,18 @@ static void work_func(struct work_struct *work)
DECLARE_WORK(work, work_func); DECLARE_WORK(work, work_func);
int init_module(void) static int myinit(void)
{ {
queue = create_singlethread_workqueue("myworkqueue"); queue = create_singlethread_workqueue("myworkqueue");
queue_work(queue, &work); queue_work(queue, &work);
return 0; return 0;
} }
void cleanup_module(void) static void myexit(void)
{ {
/* Waits for jobs to finish. */ /* Waits for jobs to finish. */
destroy_workqueue(queue); destroy_workqueue(queue);
} }
module_init(myinit)
module_exit(myexit)

13
kmod.md
View File

@@ -1,6 +1,10 @@
# kmod # 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: <https://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git>
The other tools are just symlinks to it. 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 ## modprobe
List available modules relative path to `/lib/modules/VERSION/`: Vs `insmod`:
- <https://askubuntu.com/questions/20070/whats-the-difference-between-insmod-and-modprobe>
- <https://stackoverflow.com/questions/22891705/whats-the-difference-between-insmod-and-modprobe>
List available modules relative path to `/lib/modules/$KERNEL_VERSION/`:
sudo modprobe -l sudo modprobe -l