Posted onEdited onIn编程相关Views: Word count in article: 992Reading time ≈4 mins.
This post will give a simple introduction to Linux kernel module(Part I.).
Linux kernel module简介(一)
When your system has a new external chip connected(I2C,SPI,GPIO etc.), you might need to write a driver for it by yourself. Normally this driver will be implemented as a kernel module.
Kernel module development is a complex task and it’s hard to make it clear in one simple post. If you want to learn more, a good choice is taking a look at Linux kernel source code.
This simple example shows basic structure of kernel module. A init function and a exit function must be declared, to avoid warnings, MODULE_AUTHOR and MODULE_LICENSE is needed as well.
Makefile
To compile it to kernel module(.ko) file, we need to write a Makefile for it.
1 2 3
simple-module-objs := simple_module.o
obj-m := simple-module.o
In this Makefile $(-objs) lists all objects used to link the final executable, obj-m means loadable module goals, it will generate a standalone .ko file, then we can use insmod to install it. If change it to obj-y, it will be compiled into kernel.
as for marco __init , It tells the compiler to put this function in a special section, which is declared in vmlinux.lds. __init puts the function in the “.init.text” section.
Take a look at where it defined(/linux-4.9/include/linux/init.h):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/* These macros are used to mark some functions or * initialized data (doesn't apply to uninitialized data) * as `initialization' functions. The kernel can take this * as hint that the function is used only during the initialization * phase and free up used memory resources after*/ /* These are for everybody (although not all archs will actually discard it in modules) */ #define __init __section(.init.text) #define __initdata __section(.init.data) #define __exitdata __section(.exit.data) #define __exit_call __used __section(.exitcall.exit)
What are module_i2c_driver and MODULE_DEVICE_TABLE
Like module_init we mentioned, they are marcos as well. Use your holy F12:
1 2 3 4 5 6 7 8 9 10 11
/** * module_i2c_driver() - Helper macro for registering a modular I2C driver * @__i2c_driver: i2c_driver struct * * Helper macro for I2C drivers which do not do anything special in module * init/exit. This eliminates a lot of boilerplate. Each module may only * use this macro once, and calling it replaces module_init() and module_exit() */ #define module_i2c_driver(__i2c_driver) \ module_driver(__i2c_driver, i2c_add_driver, \ i2c_del_driver)
/** * module_driver() - Helper macro for drivers that don't do anything * special in module init/exit. This eliminates a lot of boilerplate. * Each module may only use this macro once, and calling it replaces * module_init() and module_exit(). * * @__driver: driver name * @__register: register function for this driver type * @__unregister: unregister function for this driver type * @...: Additional arguments to be passed to __register and __unregister. * * Use this macro to construct bus specific macros for registering * drivers, and do not use it on its own. */ #define module_driver(__driver, __register, __unregister, ...) \ static int __init __driver##_init(void) \ { \ return __register(&(__driver) , ##__VA_ARGS__); \ } \ module_init(__driver##_init); \ static void __exit __driver##_exit(void) \ { \ __unregister(&(__driver) , ##__VA_ARGS__); \ } \ module_exit(__driver##_exit);
As you can see, those marcos actually are encapsulations of module_init/exit.
And for MODULE_DEVICE_TABLE, it’s just help to create an alias, if there is any nodes in dts has the same compatible with your drivers, probe function will be called. As a driver writer, you have no idea how will user enumerate it(By of or i2c), so provide both of them is necessary.
1 2 3 4 5 6 7 8
#ifdef MODULE /* Creates an alias so file2alias.c can find device table. */ #define MODULE_DEVICE_TABLE(type, name) \ extern typeof(name) __mod_##type##__##name##_device_table \ __attribute__ ((unused, alias(__stringify(name)))) #else/* !MODULE */ #define MODULE_DEVICE_TABLE(type, name) #endif