Statistics
11
Views
0
Downloads
0
Donations
Support
Share
Uploader

高宏飞

Shared on 2026-01-09

AuthorPeter Jay Salzman, Michael Burian, Ori Pomerantz, Bob Mottram, Jim Huang

A book on linux kernel modules

Tags
No tags
Publisher: sysprog21
Publish Year: 2025
Language: 英文
Pages: 129
File Format: PDF
File Size: 1.1 MB
Support Statistics
¥.00 · 0times
Text Preview (First 20 pages)
Registered users can read the full content for free

Register as a Gaohf Library member to read the complete e-book online for free and enjoy a better reading experience.

The Linux Kernel Module Programming Guide Peter Jay Salzman, Michael Burian, Ori Pomerantz, Bob Mottram, Jim Huang December 12, 2024
Peter Jay Salzman, Michael Burian, Ori Pomerantz, Bob Mottram, Jim Huang
Contents 1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.1 Authorship . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.2 Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 4 1.3 What Is A Kernel Module? . . . . . . . . . . . . . . . . . 5 1.4 Kernel module package . . . . . . . . . . . . . . . . . . . 5 1.5 What Modules are in my Kernel? . . . . . . . . . . . . . . 5 1.6 Is there a need to download and compile the kernel? . . . 6 1.7 Before We Begin . . . . . . . . . . . . . . . . . . . . . . . 6 2 Headers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 4 Hello World . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 4.1 The Simplest Module . . . . . . . . . . . . . . . . . . . . 8 4.2 Hello and Goodbye . . . . . . . . . . . . . . . . . . . . . . 13 4.3 The __init and __exit Macros . . . . . . . . . . . . . . 14 4.4 Licensing and Module Documentation . . . . . . . . . . . 15 4.5 Passing Command Line Arguments to a Module . . . . . 15 4.6 Modules Spanning Multiple Files . . . . . . . . . . . . . . 18 4.7 Building modules for a precompiled kernel . . . . . . . . . 19 5 Preliminaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 5.1 How modules begin and end . . . . . . . . . . . . . . . . . 22 5.2 Functions available to modules . . . . . . . . . . . . . . . 22 5.3 User Space vs Kernel Space . . . . . . . . . . . . . . . . . 23 5.4 Name Space . . . . . . . . . . . . . . . . . . . . . . . . . . 24 5.5 Code space . . . . . . . . . . . . . . . . . . . . . . . . . . 24 5.6 Device Drivers . . . . . . . . . . . . . . . . . . . . . . . . 25 6 Character Device drivers . . . . . . . . . . . . . . . . . . . . . . . 26 6.1 The file_operations Structure . . . . . . . . . . . . . . . . 26 6.2 The file structure . . . . . . . . . . . . . . . . . . . . . . . 28 2
6.3 Registering A Device . . . . . . . . . . . . . . . . . . . . . 29 6.4 Unregistering A Device . . . . . . . . . . . . . . . . . . . 30 6.5 chardev.c . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 6.6 Writing Modules for Multiple Kernel Versions . . . . . . . 35 7 The /proc File System . . . . . . . . . . . . . . . . . . . . . . . . 35 7.1 The proc_ops Structure . . . . . . . . . . . . . . . . . . . 37 7.2 Read and Write a /proc File . . . . . . . . . . . . . . . . 37 7.3 Manage /proc file with standard filesystem . . . . . . . . 40 7.4 Manage /proc file with seq_file . . . . . . . . . . . . . . . 42 8 sysfs: Interacting with your module . . . . . . . . . . . . . . . . . 46 9 Talking To Device Files . . . . . . . . . . . . . . . . . . . . . . . 49 10 System Calls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 11 Blocking Processes and threads . . . . . . . . . . . . . . . . . . . 70 11.1 Sleep . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70 11.2 Completions . . . . . . . . . . . . . . . . . . . . . . . . . 77 12 Avoiding Collisions and Deadlocks . . . . . . . . . . . . . . . . . 79 12.1 Mutex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 12.2 Spinlocks . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 12.3 Read and write locks . . . . . . . . . . . . . . . . . . . . . 81 12.4 Atomic operations . . . . . . . . . . . . . . . . . . . . . . 83 13 Replacing Print Macros . . . . . . . . . . . . . . . . . . . . . . . 85 13.1 Replacement . . . . . . . . . . . . . . . . . . . . . . . . . 85 13.2 Flashing keyboard LEDs . . . . . . . . . . . . . . . . . . . 86 14 Scheduling Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 14.1 Tasklets . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 14.2 Work queues . . . . . . . . . . . . . . . . . . . . . . . . . 91 15 Interrupt Handlers . . . . . . . . . . . . . . . . . . . . . . . . . . 92 15.1 Interrupt Handlers . . . . . . . . . . . . . . . . . . . . . . 92 15.2 Detecting button presses . . . . . . . . . . . . . . . . . . . 93 15.3 Bottom Half . . . . . . . . . . . . . . . . . . . . . . . . . 97 15.4 Threaded IRQ . . . . . . . . . . . . . . . . . . . . . . . . 101 16 Virtual Input Device Driver . . . . . . . . . . . . . . . . . . . . . 106 17 Standardizing the interfaces: The Device Model . . . . . . . . . . 118 18 Optimizations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 18.1 Likely and Unlikely conditions . . . . . . . . . . . . . . . 120 18.2 Static keys . . . . . . . . . . . . . . . . . . . . . . . . . . 121 19 Common Pitfalls . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 19.1 Using standard libraries . . . . . . . . . . . . . . . . . . . 125 19.2 Disabling interrupts . . . . . . . . . . . . . . . . . . . . . 126 20 Where To Go From Here? . . . . . . . . . . . . . . . . . . . . . . 126
1 Introduction The Linux Kernel Module Programming Guide is a free book; you may repro- duce and/or modify it under the terms of the Open Software License, version 3.0. This book is distributed in the hope that it would be useful, but without any warranty, without even the implied warranty of merchantability or fitness for a particular purpose. The author encourages wide distribution of this book for personal or com- mercial use, provided the above copyright notice remains intact and the method adheres to the provisions of the Open Software License. In summary, you may copy and distribute this book free of charge or for a profit. No explicit permis- sion is required from the author for reproduction of this book in any medium, physical or electronic. Derivative works and translations of this document must be placed un- der the Open Software License, and the original copyright notice must remain intact. If you have contributed new material to this book, you must make the material and source code available for your revisions. Please make revi- sions and updates available directly to the document maintainer, Jim Huang <jserv@ccns.ncku.edu.tw>. This will allow for the merging of updates and provide consistent revisions to the Linux community. If you publish or distribute this book commercially, donations, royalties, and/or printed copies are greatly appreciated by the author and the Linux Documentation Project (LDP). Contributing in this way shows your support for free software and the LDP. If you have questions or comments, please contact the address above. 1.1 Authorship The Linux Kernel Module Programming Guide was initially authored by Ori Pomerantz for Linux v2.2. As the Linux kernel evolved, Ori’s availability to maintain the document diminished. Consequently, Peter Jay Salzman assumed the role of maintainer and updated the guide for Linux v2.4. Similar constraints arose for Peter when tracking developments in Linux v2.6, leading to Michael Burian joining as a co-maintainer to bring the guide up to speed with Linux v2.6. Bob Mottram contributed to the guide by updating examples for Linux v3.8 and later. Jim Huang then undertook the task of updating the guide for recent Linux versions (v5.0 and beyond), along with revising the LaTeX document. 1.2 Acknowledgements The following people have contributed corrections or good suggestions: Amit Dhingra, Andy Shevchenko, Arush Sharma, Benno Bielmeier, Bob Lee, Brad Baker, Che-Chia Chang, Cheng-Shian Yeh, Chih-En Lin, Chih-Hsuan Yang, Chih-Yu Chen, Ching-Hua (Vivian) Lin, Chin Yik Ming, cvvletter,
Cyril Brulebois, Daniele Paolo Scarpazza, David Porter, demonsome, Dimo Velev, Ekang Monyet, Ethan Chan, Francois Audeon, Gilad Reti, heartofrain, Horst Schirmeier, Hsin-Hsiang Peng, Ignacio Martin, I-Hsin Cheng, Iûnn Kiàn-îng, Jian-Xing Wu, Johan Calle, keytouch, Kohei Otsuka, Kuan-Wei Chiu, manbing, Marconi Jiang, mengxinayan, Meng-Zong Tsai, Peter Lin, Roman Lakeev, Sam Erickson, Shao-Tse Hung, Shih-Sheng Yang, Stacy Prowell, Steven Lung, Tristan Lelong, Tse-Wei Lin, Tucker Polomik, Tyler Fanelli, VxTeemo, Wei-Hsin Yeh, Wei-Lun Tsai, Xatierlike Lee, Yen-Yu Chen, Yin-Chiuan Chen, Yi-Wei Lin, Yo-Jung Lin, Yu-Hsiang Tseng, YYGO. 1.3 What Is A Kernel Module? Involvement in the development of Linux kernel modules requires a foundation in the C programming language and a track record of creating conventional programs intended for process execution. This pursuit delves into a domain where an unregulated pointer, if disregarded, may potentially trigger the total elimination of an entire file system, resulting in a scenario that necessitates a complete system reboot. A Linux kernel module is precisely defined as a code segment capable of dynamic loading and unloading within the kernel as needed. These modules enhance kernel capabilities without necessitating a system reboot. A notable example is seen in the device driver module, which facilitates kernel interaction with hardware components linked to the system. In the absence of modules, the prevailing approach leans toward monolithic kernels, requiring direct integration of new functionalities into the kernel image. This approach leads to larger ker- nels and necessitates kernel rebuilding and subsequent system rebooting when new functionalities are desired. 1.4 Kernel module package Linux distributions provide the commands modprobe, insmod and depmod within a package. On Ubuntu/Debian GNU/Linux: 1 sudo apt-get install build-essential kmod On Arch Linux: 1 sudo pacman -S gcc kmod 1.5 What Modules are in my Kernel? To discover what modules are already loaded within your current kernel use the command lsmod.
1 lsmod Modules are stored within the file /proc/modules, so you can also see them with: 1 cat /proc/modules This can be a long list, and you might prefer to search for something partic- ular. To search for the fat module: 1 lsmod | grep fat 1.6 Is there a need to download and compile the kernel? To effectively follow this guide, there is no obligatory requirement for performing such actions. Nonetheless, a prudent approach involves executing the examples within a test distribution on a virtual machine, thus mitigating any potential risk of disrupting the system. 1.7 Before We Begin Before delving into code, certain matters require attention. Variances exist among individuals’ systems, and distinct personal approaches are evident. The achievement of successful compilation and loading of the inaugural “hello world” program may, at times, present challenges. It is reassuring to note that over- coming the initial obstacle in the first attempt paves the way for subsequent endeavors to proceed seamlessly. 1. Modversioning. A module compiled for one kernel will not load if a differ- ent kernel is booted, unless CONFIG_MODVERSIONS is enabled in the kernel. Module versioning will be discussed later in this guide. Until module versioning is covered, the examples in this guide may not work correctly if running a kernel with modversioning turned on. However, most stock Linux distribution kernels come with modversioning enabled. If difficul- ties arise when loading the modules due to versioning errors, consider compiling a kernel with modversioning turned off. 2. Using X Window System. It is highly recommended to extract, compile, and load all the examples discussed in this guide from a console. Working on these tasks within the X Window System is discouraged. Modules cannot directly print to the screen like printf() can, but they can log information and warnings that are eventually displayed on the screen, specifically within a console. If a module is loaded from an xterm,
the information and warnings will be logged, but solely within the systemd journal. These logs will not be visible unless consulting the journalctl. Refer to 4 for more information. For instant access to this information, it is advisable to perform all tasks from the console. 3. SecureBoot. Numerous modern computers arrive pre-configured with UEFI SecureBoot enabled—an essential security standard ensuring booting ex- clusively through trusted software endorsed by the original equipment manufacturer. Certain Linux distributions even ship with the default Linux kernel configured to support SecureBoot. In these cases, the kernel module necessitates a signed security key. Failing this, an attempt to insert your first “hello world” module would result in the message: “ERROR: could not insert module”. If this message Lockdown: insmod: unsigned module loading is restricted; see man kernel lockdown.7 appears in the dmesg output, the simplest approach involves disabling UEFI SecureBoot from the boot menu of your PC or laptop, allowing the successful insertion of “hello world” module. Naturally, an al- ternative involves undergoing intricate procedures such as generating keys, system key installation, and module signing to achieve functionality. How- ever, this intricate process is less appropriate for beginners. If interested, more detailed steps for SecureBoot can be explored and followed. 2 Headers Before building anything, it is necessary to install the header files for the kernel. On Ubuntu/Debian GNU/Linux: 1 sudo apt-get update 2 apt-cache search linux-headers-`uname -r` The following command provides information on the available kernel header files. Then for example: 1 sudo apt-get install kmod linux-headers-5.4.0-80-generic On Arch Linux: 1 sudo pacman -S linux-headers On Fedora: 1 sudo dnf install kernel-devel kernel-headers
3 Examples All the examples from this document are available within the examples subdi- rectory. Should compile errors occur, it may be due to a more recent kernel version being in use, or there might be a need to install the corresponding kernel header files. 4 Hello World 4.1 The Simplest Module Most individuals beginning their programming journey typically start with some variant of a hello world example. It is unclear what the outcomes are for those who deviate from this tradition, but it seems prudent to adhere to it. The learning process will begin with a series of hello world programs that illustrate various fundamental aspects of writing a kernel module. Presented next is the simplest possible module. Make a test directory: 1 mkdir -p ~/develop/kernel/hello-1 2 cd ~/develop/kernel/hello-1 Paste this into your favorite editor and save it as hello-1.c: 1 /* 2 * hello-1.c - The simplest kernel module. 3 */ 4 #include <linux/module.h> /* Needed by all modules */ 5 #include <linux/printk.h> /* Needed for pr_info() */ 6 7 int init_module(void) 8 { 9 pr_info("Hello world 1.\n"); 10 11 /* A non 0 return means init_module failed; module can't be loaded. */ 12 return 0; 13 } 14 15 void cleanup_module(void) 16 { 17 pr_info("Goodbye world 1.\n"); 18 } 19 20 MODULE_LICENSE("GPL"); Now you will need a Makefile. If you copy and paste this, change the indentation to use tabs, not spaces.
1 obj-m += hello-1.o 2 3 PWD := $(CURDIR) 4 5 all: 6 $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 7 8 clean: 9 $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean In Makefile, $(CURDIR) can set to the absolute pathname of the current working directory(after all -C options are processed, if any). See more about CURDIR in GNU make manual. And finally, just run make directly. 1 make If there is no PWD := $(CURDIR) statement in Makefile, then it may not compile correctly with sudo make. Because some environment variables are specified by the security policy, they can’t be inherited. The default security policy is sudoers. In the sudoers security policy, env_reset is enabled by default, which restricts environment variables. Specifically, path variables are not retained from the user environment, they are set to default values (For more information see: sudoers manual). You can see the environment variable settings by: $ sudo -s # sudo -V Here is a simple Makefile as an example to demonstrate the problem men- tioned above. 1 all: 2 echo $(PWD) Then, we can use -p flag to print out the environment variable values from the Makefile. $ make -p | grep PWD PWD = /home/ubuntu/temp OLDPWD = /home/ubuntu echo $(PWD) The PWD variable won’t be inherited with sudo.
$ sudo make -p | grep PWD echo $(PWD) However, there are three ways to solve this problem. 1. You can use the -E flag to temporarily preserve them. 1 $ sudo -E make -p | grep PWD 2 PWD = /home/ubuntu/temp 3 OLDPWD = /home/ubuntu 4 echo $(PWD) 2. You can set the env_reset disabled by editing the /etc/sudoers with root and visudo. 1 ## sudoers file. 2 ## 3 ... 4 Defaults env_reset 5 ## Change env_reset to !env_reset in previous line to keep all environment variables↪→ Then execute env and sudo env individually. 1 # disable the env_reset 2 echo "user:" > non-env_reset.log; env >> non-env_reset.log↪→ 3 echo "root:" >> non-env_reset.log; sudo env >> non-env_reset.log↪→ 4 # enable the env_reset 5 echo "user:" > env_reset.log; env >> env_reset.log 6 echo "root:" >> env_reset.log; sudo env >> env_reset.log↪→ You can view and compare these logs to find differences between env_reset and !env_reset. 3. You can preserve environment variables by appending them to env_keep in /etc/sudoers. 1 Defaults env_keep += "PWD"
After applying the above change, you can check the environment variable settings by: $ sudo -s # sudo -V If all goes smoothly you should then find that you have a compiled hello-1.ko module. You can find info on it with the command: 1 modinfo hello-1.ko At this point the command: 1 lsmod | grep hello should return nothing. You can try loading your shiny new module with: 1 sudo insmod hello-1.ko The dash character will get converted to an underscore, so when you again try: 1 lsmod | grep hello You should now see your loaded module. It can be removed again with: 1 sudo rmmod hello_1 Notice that the dash was replaced by an underscore. To see what just hap- pened in the logs: 1 journalctl --since "1 hour ago" | grep kernel You now know the basics of creating, compiling, installing and removing modules. Now for more of a description of how this module works. Kernel modules must have at least two functions: a "start" (initialization) function called init_module() which is called when the module is insmoded into the kernel, and an "end" (cleanup) function called cleanup_module() which is called just before it is removed from the kernel. Actually, things have changed starting with kernel 2.3.13. You can now use whatever name you like for the start and end functions of a module, and you will learn how to do this in Section 4.2.
In fact, the new method is the preferred method. However, many people still use init_module() and cleanup_module() for their start and end functions. Typically, init_module() either registers a handler for something with the kernel, or it replaces one of the kernel functions with its own code (usually code to do something and then call the original function). The cleanup_module() function is supposed to undo whatever init_module() did, so the module can be unloaded safely. Lastly, every kernel module needs to include <linux/module.h>. We needed to include <linux/printk.h> only for the macro expansion for the pr_alert() log level, which you’ll learn about in Section 2. 1. A point about coding style. Another thing which may not be immediately obvious to anyone getting started with kernel programming is that inden- tation within your code should be using tabs and not spaces. It is one of the coding conventions of the kernel. You may not like it, but you’ll need to get used to it if you ever submit a patch upstream. 2. Introducing print macros. In the beginning there was printk, usually fol- lowed by a priority such as KERN_INFO or KERN_DEBUG. More recently this can also be expressed in abbreviated form using a set of print macros, such as pr_info and pr_debug. This just saves some mindless key- board bashing and looks a bit neater. They can be found within in- clude/linux/printk.h. Take time to read through the available priority macros. 3. About Compiling. Kernel modules need to be compiled a bit differently from regular userspace apps. Former kernel versions required us to care much about these settings, which are usually stored in Makefiles. Al- though hierarchically organized, many redundant settings accumulated in sublevel Makefiles and made them large and rather difficult to maintain. Fortunately, there is a new way of doing these things, called kbuild, and the build process for external loadable modules is now fully integrated into the standard kernel build mechanism. To learn more on how to compile modules which are not part of the official kernel (such as all the examples you will find in this guide), see file Documentation/kbuild/modules.rst. Additional details about Makefiles for kernel modules are available in Doc- umentation/kbuild/makefiles.rst. Be sure to read this and the related files before starting to hack Makefiles. It will probably save you lots of work. Here is another exercise for the reader. See that comment above the return statement in init_module()? Change the return value to something negative, recompile and load the module again. What happens?
4.2 Hello and Goodbye In early kernel versions you had to use the init_module and cleanup_module functions, as in the first hello world example, but these days you can name those anything you want by using the module_init and module_exit macros. These macros are defined in include/linux/module.h. The only requirement is that your init and cleanup functions must be defined before calling the those macros, otherwise you’ll get compilation errors. Here is an example of this technique: 1 /* 2 * hello-2.c - Demonstrating the module_init() and module_exit() macros. 3 * This is preferred over using init_module() and cleanup_module(). 4 */ 5 #include <linux/init.h> /* Needed for the macros */ 6 #include <linux/module.h> /* Needed by all modules */ 7 #include <linux/printk.h> /* Needed for pr_info() */ 8 9 static int __init hello_2_init(void) 10 { 11 pr_info("Hello, world 2\n"); 12 return 0; 13 } 14 15 static void __exit hello_2_exit(void) 16 { 17 pr_info("Goodbye, world 2\n"); 18 } 19 20 module_init(hello_2_init); 21 module_exit(hello_2_exit); 22 23 MODULE_LICENSE("GPL"); So now we have two real kernel modules under our belt. Adding another module is as simple as this: 1 obj-m += hello-1.o 2 obj-m += hello-2.o 3 4 PWD := $(CURDIR) 5 6 all: 7 $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 8 9 clean: 10 $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean Now have a look at drivers/char/Makefile for a real world example. As you can see, some things got hardwired into the kernel (obj-y) but where have all those obj-m gone? Those familiar with shell scripts will easily be able to spot them. For those who are not, the obj-$(CONFIG_FOO) entries you see
everywhere expand into obj-y or obj-m, depending on whether the CONFIG_FOO variable has been set to y or m. While we are at it, those were exactly the kind of variables that you have set in the .config file in the top-level directory of Linux kernel source tree, the last time when you said make menuconfig or something like that. 4.3 The __init and __exit Macros The __init macro causes the init function to be discarded and its memory freed once the init function finishes for built-in drivers, but not loadable modules. If you think about when the init function is invoked, this makes perfect sense. There is also an __initdata which works similarly to __init but for init variables rather than functions. The __exit macro causes the omission of the function when the module is built into the kernel, and like __init, has no effect for loadable modules. Again, if you consider when the cleanup function runs, this makes complete sense; built-in drivers do not need a cleanup function, while loadable modules do. These macros are defined in include/linux/init.h and serve to free up kernel memory. When you boot your kernel and see something like Freeing unused kernel memory: 236k freed, this is precisely what the kernel is freeing. 1 /* 2 * hello-3.c - Illustrating the __init, __initdata and __exit macros. 3 */ 4 #include <linux/init.h> /* Needed for the macros */ 5 #include <linux/module.h> /* Needed by all modules */ 6 #include <linux/printk.h> /* Needed for pr_info() */ 7 8 static int hello3_data __initdata = 3; 9 10 static int __init hello_3_init(void) 11 { 12 pr_info("Hello, world %d\n", hello3_data); 13 return 0; 14 } 15 16 static void __exit hello_3_exit(void) 17 { 18 pr_info("Goodbye, world 3\n"); 19 } 20 21 module_init(hello_3_init); 22 module_exit(hello_3_exit); 23 24 MODULE_LICENSE("GPL");
4.4 Licensing and Module Documentation Honestly, who loads or even cares about proprietary modules? If you do then you might have seen something like this: $ sudo insmod xxxxxx.ko loading out-of-tree module taints kernel. module license 'unspecified' taints kernel. You can use a few macros to indicate the license for your module. Some ex- amples are "GPL", "GPL v2", "GPL and additional rights", "Dual BSD/GPL", "Dual MIT/GPL", "Dual MPL/GPL" and "Proprietary". They are defined within include/linux/module.h. To reference what license you’re using a macro is available called MODULE_LICENSE. This and a few other macros describing the module are illustrated in the below example. 1 /* 2 * hello-4.c - Demonstrates module documentation. 3 */ 4 #include <linux/init.h> /* Needed for the macros */ 5 #include <linux/module.h> /* Needed by all modules */ 6 #include <linux/printk.h> /* Needed for pr_info() */ 7 8 MODULE_LICENSE("GPL"); 9 MODULE_AUTHOR("LKMPG"); 10 MODULE_DESCRIPTION("A sample driver"); 11 12 static int __init init_hello_4(void) 13 { 14 pr_info("Hello, world 4\n"); 15 return 0; 16 } 17 18 static void __exit cleanup_hello_4(void) 19 { 20 pr_info("Goodbye, world 4\n"); 21 } 22 23 module_init(init_hello_4); 24 module_exit(cleanup_hello_4); 4.5 Passing Command Line Arguments to a Module Modules can take command line arguments, but not with the argc/argv you might be used to. To allow arguments to be passed to your module, declare the variables that will take the values of the command line arguments as global and then use the module_param() macro, (defined in include/linux/moduleparam.h) to set the mechanism up. At runtime, insmod will fill the variables with any command line
arguments that are given, like insmod mymodule.ko myvariable=5. The vari- able declarations and macros should be placed at the beginning of the module for clarity. The example code should clear up my admittedly lousy explanation. The module_param() macro takes 3 arguments: the name of the variable, its type and permissions for the corresponding file in sysfs. Integer types can be signed as usual or unsigned. If you’d like to use arrays of integers or strings see module_param_array() and module_param_string(). 1 int myint = 3; 2 module_param(myint, int, 0); Arrays are supported too, but things are a bit different now than they were in the olden days. To keep track of the number of parameters you need to pass a pointer to a count variable as third parameter. At your option, you could also ignore the count and pass NULL instead. We show both possibilities here: 1 int myintarray[2]; 2 module_param_array(myintarray, int, NULL, 0); /* not interested in count */ 3 4 short myshortarray[4]; 5 int count; 6 module_param_array(myshortarray, short, &count, 0); /* put count into "count" variable */↪→ A good use for this is to have the module variable’s default values set, like a port or IO address. If the variables contain the default values, then perform autodetection (explained elsewhere). Otherwise, keep the current value. This will be made clear later on. Lastly, there is a macro function, MODULE_PARM_DESC(), that is used to document arguments that the module can take. It takes two parameters: a variable name and a free form string describing that variable. 1 /* 2 * hello-5.c - Demonstrates command line argument passing to a module. 3 */ 4 #include <linux/init.h> 5 #include <linux/kernel.h> /* for ARRAY_SIZE() */ 6 #include <linux/module.h> 7 #include <linux/moduleparam.h> 8 #include <linux/printk.h> 9 #include <linux/stat.h> 10 11 MODULE_LICENSE("GPL"); 12 13 static short int myshort = 1; 14 static int myint = 420; 15 static long int mylong = 9999; 16 static char *mystring = "blah"; 17 static int myintarray[2] = { 420, 420 }; 18 static int arr_argc = 0;
19 20 /* module_param(foo, int, 0000) 21 * The first param is the parameter's name. 22 * The second param is its data type. 23 * The final argument is the permissions bits, 24 * for exposing parameters in sysfs (if non-zero) at a later stage. 25 */ 26 module_param(myshort, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); 27 MODULE_PARM_DESC(myshort, "A short integer"); 28 module_param(myint, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 29 MODULE_PARM_DESC(myint, "An integer"); 30 module_param(mylong, long, S_IRUSR); 31 MODULE_PARM_DESC(mylong, "A long integer"); 32 module_param(mystring, charp, 0000); 33 MODULE_PARM_DESC(mystring, "A character string"); 34 35 /* module_param_array(name, type, num, perm); 36 * The first param is the parameter's (in this case the array's) name. 37 * The second param is the data type of the elements of the array. 38 * The third argument is a pointer to the variable that will store the number 39 * of elements of the array initialized by the user at module loading time. 40 * The fourth argument is the permission bits. 41 */ 42 module_param_array(myintarray, int, &arr_argc, 0000); 43 MODULE_PARM_DESC(myintarray, "An array of integers"); 44 45 static int __init hello_5_init(void) 46 { 47 int i; 48 49 pr_info("Hello, world 5\n=============\n"); 50 pr_info("myshort is a short integer: %hd\n", myshort); 51 pr_info("myint is an integer: %d\n", myint); 52 pr_info("mylong is a long integer: %ld\n", mylong); 53 pr_info("mystring is a string: %s\n", mystring); 54 55 for (i = 0; i < ARRAY_SIZE(myintarray); i++) 56 pr_info("myintarray[%d] = %d\n", i, myintarray[i]); 57 58 pr_info("got %d arguments for myintarray.\n", arr_argc); 59 return 0; 60 } 61 62 static void __exit hello_5_exit(void) 63 { 64 pr_info("Goodbye, world 5\n"); 65 } 66 67 module_init(hello_5_init); 68 module_exit(hello_5_exit); It is recommended to experiment with the following code: $ sudo insmod hello-5.ko mystring="bebop" myintarray=-1 $ sudo dmesg -t | tail -7 myshort is a short integer: 1
myint is an integer: 420 mylong is a long integer: 9999 mystring is a string: bebop myintarray[0] = -1 myintarray[1] = 420 got 1 arguments for myintarray. $ sudo rmmod hello-5 $ sudo dmesg -t | tail -1 Goodbye, world 5 $ sudo insmod hello-5.ko mystring="supercalifragilisticexpialidocious" myintarray=-1,-1 $ sudo dmesg -t | tail -7 myshort is a short integer: 1 myint is an integer: 420 mylong is a long integer: 9999 mystring is a string: supercalifragilisticexpialidocious myintarray[0] = -1 myintarray[1] = -1 got 2 arguments for myintarray. $ sudo rmmod hello-5 $ sudo dmesg -t | tail -1 Goodbye, world 5 $ sudo insmod hello-5.ko mylong=hello insmod: ERROR: could not insert module hello-5.ko: Invalid parameters 4.6 Modules Spanning Multiple Files Sometimes it makes sense to divide a kernel module between several source files. Here is an example of such a kernel module. 1 /* 2 * start.c - Illustration of multi filed modules 3 */ 4 5 #include <linux/kernel.h> /* We are doing kernel work */ 6 #include <linux/module.h> /* Specifically, a module */ 7 8 int init_module(void) 9 { 10 pr_info("Hello, world - this is the kernel speaking\n"); 11 return 0; 12 } 13 14 MODULE_LICENSE("GPL"); The next file:
1 /* 2 * stop.c - Illustration of multi filed modules 3 */ 4 5 #include <linux/kernel.h> /* We are doing kernel work */ 6 #include <linux/module.h> /* Specifically, a module */ 7 8 void cleanup_module(void) 9 { 10 pr_info("Short is the life of a kernel module\n"); 11 } 12 13 MODULE_LICENSE("GPL"); And finally, the makefile: 1 obj-m += hello-1.o 2 obj-m += hello-2.o 3 obj-m += hello-3.o 4 obj-m += hello-4.o 5 obj-m += hello-5.o 6 obj-m += startstop.o 7 startstop-objs := start.o stop.o 8 9 PWD := $(CURDIR) 10 11 all: 12 $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules 13 14 clean: 15 $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean This is the complete makefile for all the examples we have seen so far. The first five lines are nothing special, but for the last example we will need two lines. First we invent an object name for our combined module, second we tell make what object files are part of that module. 4.7 Building modules for a precompiled kernel Obviously, we strongly suggest you to recompile your kernel, so that you can enable a number of useful debugging features, such as forced module unloading (MODULE_FORCE_UNLOAD): when this option is enabled, you can force the kernel to unload a module even when it believes it is unsafe, via a sudo rmmod -f module command. This option can save you a lot of time and a number of reboots dur- ing the development of a module. If you do not want to recompile your kernel then you should consider running the examples within a test distribution on a virtual machine. If you mess anything up then you can easily reboot or restore the virtual machine (VM). There are a number of cases in which you may want to load your module into a precompiled running kernel, such as the ones shipped with common Linux