Article title: kernel module programming details. Linux is a technology channel of the IT lab in China. Includes basic categories such as desktop applications, Linux system management, kernel research, embedded systems, and open source.
I don't know what happened when something like module appeared in Linux. Indeed, it is a major innovation of Linux. With the module, writing the device driver is no longer a nightmare, and modifying the kernel is no longer a painful task. Because you don't need to test the driver every time and re-compile the kernel. It would be exhausting. The Module allows us to dynamically change the kernel, load the device driver, and shorten the driver development time. In this article, I will introduce the principle of the module and how to write a module.
Module translation into Chinese is a module, but in fact it is meaningless to translate this word. Before talking about the module, let me give an example. I believe many people have used RedHat. In RedHat, we can execute sndconfig to help us configure the sound card. After the configuration, if you get your sound card, your sound card will be ready for operation immediately, and you do not need to reactivate the computer. How did this happen? Module. The module is actually a general program. But it can be dynamically loaded into the kernel to become part of the kernel. The module loaded into the kernel has the same power as the kernel. You can access the data structure of any kernel. Have you heard of kdebug? It is used to debug the kernel. It first loads a module of it into the kernel, and gdb in the user space can communicate with this module to know the value of the data structure in the kernel. In addition, you can also change the data structure in the kernel through the module loaded to the kernel.
We know that when writing a C program, a program can only have one main. Kernel itself is actually a program, and it also has a main, called start_kernel (). When we load a module into the kernel, it will be integrated with the kernel to become part of the kernel. Think about it. can the module have main? The answer is obviously No. The reason is simple. A program can only have one main. When using the module, remember that the module is a passive role. It provides some functions for others to use.
There is a variable named module_list in the Kernel. every time the user loads a module into the kernel, this module will be recorded in module_list. When the kernel needs to use the function provided by the module, it will search the list, find the module, and then use the function or variable provided by the module. Each module can export some functions or variables for others to use. In addition, the module can also use the function provided by the module that has been loaded into the kernel. This situation is called module stack. For example, if module A uses module B, it is necessary to load module B before loading module. Otherwise, module A cannot be loaded. In addition to the module, the kernel itself also export some functions or variable. Similarly, the module can also use the export output by the kernel. Since we usually write user space programs, when we suddenly write a module, we will take the function used to write the program to the module for use. Something like printf. What I want to tell you is that the function or variable used by the module should be written in the module by itself, or provided by other modules, or provided by the kernel. You cannot use functions provided by libc or glibc. Something like printf. This may be something you need to be careful. (Maybe you can link it first and then load it to the kernel. I seem to have tried it, but forget it)
As we mentioned earlier, the kernel itself export some functions or variable for the module to use. However, we are not omnipotent. how do we know that there is something open in the kernel for us to use? Linux provides a command named ksyms. you only need to execute ksyms-a to know the functions or variable provided by the kernel or the module currently loaded into the kernel. The following is my system:
c0216ba0 drive_info_R744aa133c01e4a44 boot_cpu_data_R660bd466c01e4ac0 EISA_bus_R7413793ac01e4ac4 MCA_bus_Rf48a2c4cc010cc34 __verify_write_R203afbeb . . . . .
|
In the kernel, a symbol table is used to record the function or variable of the export. In addition, the functions of the module export are recorded. In the above lines, the kernel provides the function/variable drive_info. Therefore, we can use it directly in the kernel. when it is loaded into the kernel, the link action is automatically completed. As a result, we can know that the module itself is not actually link some object code. The link will not be completed until the module is loaded with the kernel. You can see some strange strings after drive_info. _ R744aa133, which is the result of some encode based on the current kernel version. Why is this extra string required?
Linux does not know that since that version, a config option has been added, called Set version number in symbols of module. This is to avoid system instability. We know that Linux kernel is updated very quickly. In the kernel update process, sometimes some old data structures or functions are changed for efficiency, and the variable may be removed, some functions have different prototypes than the original ones. If this happens, the module of version 2.0.33 may be used to get the kernel of version 2.2.1. assume that the variable of version 2.0.33 kernel is called, however, in 2.2.1, A must be set to NULL for some reason. When this module is used on 2.2.1 kernel, if it is used directly without checking the value of A, it will cause system errors. Maybe the entire system will not die, but this module is definitely difficult to use its functions. For this reason, during the compile module in Linux, encode the number of the kernel version to each exported function and variable.
So, maybe we should not say that the kernel provides drive_info, but that the kernel provides driver_info_R744aa133 for our use. You may understand this. That is to say, kernel considers it to provide the driver_info_r744aa.pdf, instead of driver_info. Therefore, when loading a module, the system always tells you that a function cannot be resolved. This is because there is no function in the kernel, or the function used in your module is different from the result of the kernel encode. Therefore, resolve cannot be performed. The solution is to turn off the set version option in the kernel, and to convert the module compile into a type that the kernel can accept.
[1] [2] [3] [4] Next page