In order to facilitate further in-depth, we use the PRINTK () function in the driver to print "Hello World", PRINTK () is the kernel's own function, specifically for printing kernel information.
When installing the driver module into the kernel, it is necessary to initialize the driver module, initialize the specific do what we do not mention, we temporarily only use PRINTK () to print "Hello World":
int first_drv_init (void)
{
PRINTK ("Hello world!\n");
return 0;
}
· About the print level of PRINTK
There is a print-level concept in the kernel:
When we enter: CAT/PROC/SYS/KERNEL/PRINTK on the Linux command line, it will print: 4 4 1 7
The first "4" indicates that the current system allows a string with a print level above 4 to be displayed on the command line, that is, the print level 3, 2, 1, 0 can be displayed, 7, 6, 5, 4 print levels can not be displayed, altogether there are 0~7 these 8 print levels, the macro definition is as follows:
#define Kern_emerg "<0>"/* 1116.www.qixoo.qixoo.com system is unusable */
#define Kern_alert "<1>"/* action must be taken immediately */
#define KERN_CRIT "<2>"/* Critical conditions */
#define KERN_ERR "<3>"/* ERROR conditions */
#define Kern_warning "<4>"/* WARNING conditions */
#define KERN_NOTICE "<5>"/* Normal but significant condition * *
#define KERN_INFO "<6>"/* Informational */
#define KERN_DEBUG "<7>"/* debug-level messages */
We can give the string print level in the Print function PRINTK: printk (kern_info "Hello world!\n");
So the "Hello World" print level is 6, we can use the VI command to open the/PROC/SYS/KERNEL/PRINTK, the first 4 modified to 7, so that kern_info decorated "Hello World" can be printed out.
· Static
Before the function int first_drv_init (void), the general habit is decorated with the static keyword: static int first_drv_init (void), which makes the int first_drv_init (void) The function is only for private functions that can be used in the First_drv.c file, which is first_drv.c, and the code in the external file cannot access the int first_drv_init (void) in FIRST_DRV.C, the advantage is that Can prevent unnecessary trouble with the name of the function, if the function is the same name and is not static decoration, compile time may be error or warning, even if the program can run can also be a puzzling problem.
· __init
In addition, in addition to using the Static keyword to modify the function, it is better to develop the habit before the function and add "__init", this is a macro definition, when the compiler to compile the driver, it will be __init modified function in the. Init.text paragraph, without __ Init will default to the. Text segment, and the various drive modules are usually run by __ Init-Modified functions will be uniformly placed into the. Init.text segment, and the kernel will load uniformly when it starts. These driver module initialization functions in the Init.text segment are released to save memory after loading.
After this analysis, the initialization function of our first drive module becomes:
static int __init first_drv_init (void)
{
PRINTK (kern_info "Hello world!\n");
return 0;
}
In fact, we often heard that the installation of drivers, also heard that the uninstall drive, then a complete driver module should also be able to be uninstalled, we can follow the previous method to write an unload function:
static int __exit first_drv_exit (void)
{
PRINTK (kern_info "Goodbye world...\n");
return 0;
}
· __exit
The function and function of the __EXIT macro definition is the same as the __init macro definition, and the function is placed in the. Exit.text section, not more.
At this time we found that first_drv.c inside the empty, only First_drv_init and first_drv_exit two functions, and even a main function is not, who will call these two functions, always can not let the compiler to specify the first execution first_drv_init , and then specify the execution of the First_drv_exit bar, which is obviously wrong, but our wishful thinking.
In fact, in first_drv.c, we do not need the main function, no matter how complex, Advanced driver module does not need to write a main function in its "drive. C" file, which is why? You may have a deeper understanding after the next blog post, and now you just need to understand that the function in the driver module is simply called by another function or application.
So who called it, the initialization function of the driver module is handled by the macro definition of Module_init (), Module_init () defines a struct, and when we write Module_init (first_drv_init), In that struct there will be a function pointer pointing to the FIRST_DRV_INIT function, and when we use the Insmod command at the command line to install the First_drv driver module, the kernel will automatically find the structure, through the function pointer to find the FIRST_DRV_ The init function is called.
Corresponding, the kernel also implements the Module_exit () macro definition to allow us to implement a call to the First_drv_exit function, using Module_exit (First_drv_exit)
Because of the use of Module_init () and Module_exit () These two macro definitions, we need to add linux/module.h This header file, we have also used the __init and __exit these two macro definitions, also need to add header file linux/ Init.h
Our first shell driver was completed, why is it empty shell, because this driver can only be installed and uninstalled, not involving hardware operations, more importantly, it can not be called by the application, it does not have the interface between the application layer, we know that you have a mess in the brain, I will explain the simple relationship between the various levels of the system in the next blog post, and you will have a much clearer idea.
The complete code we wrote in this blog post is attached below:
#include "linux/module.h"//Here is not using <> but "", because the content between <> of blog edits will not be displayed
#include "linux/init.h"//<> or "" is not a big difference, but it is recommended that you use <>
static int __init first_drv_init (void)
{
PRINTK (kern_info "Hello world!\n");
return 0;
}
static int __exit first_drv_exit (void)
{
PRINTK (kern_info "Goodbye world...\n");
return 0;
}
Module_init (First_drv_init);
Module_exit (First_drv_exit);
It also has a deficiency, we will be in the next post to improve, and then to test, you can first knock it into your first_drv.c, do not copy, it is best to follow the idea of this blog post from beginning to end, step by step to perfect the above.
1th Linux driver ___ print "Hello World"