The understanding of the Makefile in the Linux driver development module & hello kernel module example

  

For a simple driver module, the following is the classic composition of the Makefile:
//------------ Makefile---------------------- obj-m := hello.o KERNELDIR := /lib/modules/$(shell uname -r)/build PWD : = $(shell pwd) modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules #note the front must be tab modules_install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install #Note that you must analyze each statement one by one for tab

:
obj-m := hello.o

This sentence means that there is a module that needs to be from the target file hello.o Constructed, the module name is hello.ko.

KERNELDIR := /lib/modules/$(shell uname -r)/build

Here is a variable KERNELDIR defined And the assignment is "/lib/modules/$(shell uname -r)/build".
The only thing to explain in this value is $(shell uname -r):


You can try to enter $:uname -r in the terminal. Wrong, this command will get the version number of the current kernel, such as “2.6.38.2”.
Then we look at the files in the "/lib/modules" directory:


$:ls /lib/modules/

The result is:

< Br>2.6.38.2 2.6.38-8-generic


So the meaning of "/lib/modules/$(shell uname -r)/build" is already clear, that is The current kernel source code directory

PWD := $(shell pwd)

With the explanation of KERNELDIR, I believe this is not to say much, just to get the current directory. In short, in the shell, $(shell xxx) is equivalent to executing the xxx command in the terminal.

$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

This is the compilation module: first change the directory to the location specified by the -C option (ie The kernel source directory), which holds the kernel's top-level makefile; the M= option causes the makefile to return to the module source directory before constructing the modules target; then, the modueles target points to the module set in the obj-m variable; In the example, we set this variable to hello.o. (— quoted from ldd3 P29)

ps

In the ldd3 P29 page, when you talk about Makefile, there is an example like this:
//Makefile is very simple obj-m := hello.o

But when compiling the module, use the following command:
$:make -C ~/kernel-2.6 M='pwd' modules

where" ~/kernel-2.6" is the kernel source tree directory, depending on where you place it, so the command for the native environment is:
$:make -C /usr/src/linux-source-2.6. 38 M=$PWD modules

The final result is exactly the same as the first method!

Now, let's compare these two methods to know, in fact, the only difference between them is that the source directory is not the same, respectively, "/lib/modules/$(shell uname -r)/build" And "/usr/src/linux-source-2.6.38/", but if you compile the kernel, you will know that the source code in the usr directory is generally decompressed after we download it, and the lib directory is Automatically copy the past at compile time, the file structure of the two is exactly the same, so it is not surprising that the make effect is exactly the same.
Hello, kernel module example

When learning C language, we will learn hello, world program in the first chapter, I believe everyone thinks it is so simple that I repeat the following program, everyone I think it's superfluous:
C++ code#include <stdio.h>

  • int main()
    {
  • printf(“hello,world/n”)
    return 0;
  • }

    Please ask the students to think about two questions: Why do we have to write a main() function? Does the kernel C program need main?

    here #include <stdio.h> is for us to use printf(), in fact they are all functions of the C language library, can they be used in the kernel program?

    We first answer these two questions. The C language application must have a main() function because it is the entry point of the application. As for why it is such an entry, we only have one answer: , mandatory. C applications have application specifications, as kernel modules have kernel modules, so when we write the kernel module framework, remember that this is the rule.

    As for the second question, it is more important: the application can call the function of the C standard library, and the kernel program is absolutely impossible. If you remember that we said fopen, it is dependent on the open system call. And if the system call is exported by the kernel, then if we can use the standard function library in the kernel program, then we will go to the "circle of the chicken" or the egg chicken.

    The following program is the standard framework for the Linux kernel module (please see how the teacher wrote this code when I first learned).
    C++ code#include <linux/module.h>

  • #include <linux/init.h>
    #include <linux/kernel.h> //Use printk, need Include this file
  • MODULE_LICENSE(“Dual BSD/GPL”);
    MODULE_AUTHOR(“stephanxu@eetek”);
  • MODULE_DESCRIPTION(“the first kernel module”) < Br> static int __init hello_init(void)
  • {
    return 0;
  • }
    static void __exit hello_exit(void)
  • {
    }
  • module_init(hello_init);
    module_exit(hello_exit);




    This is a hello Kernel module framework, if we want to print out hello, kernel, we only need to modify hello_init to: static int __init hello_init(void){ printk(“hello,kernel/n”); return 0;} module framework Contains the following four parts:

    (1) The module_init(function) that the module needs to execute when it is loaded, and the module_init The function specified in (), module_exit(function) executed when the module is unloaded, and the function defined in module_exit(). If module_exit() is declared, the module will not have dynamic unloading.

    (2) Need to define the initialization function called by module_init() and the cleanup function used in module_exit(). Only when the initialization function returns a non-negative value (because in the kernel, a negative value indicates that the operation failed), the kernel module can be loaded correctly, otherwise the module fails to load. The cleanup function returns a void type. In general, the initialization function is used to apply for resources when the module is loaded, and the cleanup function is used to release resources when the module is unloaded, which is similar to the constructor and deconstructor in C++.

    (3) Header files, for kernel modules, you must use <linux/module.h> and <linux/init.h>. It's important to note that <> is used to include header files, but it's obvious that neither of these header files will be the header of a standard function, because, as mentioned earlier, kernel modules cannot reference standard libraries. The function. The header file here actually comes from the $(KERNELSRC)/include directory in the Linux kernel source path.

    (4) Related content represented by MODULE_XXX, these are descriptions of the current kernel module, although not required, but in general, please fill in a few items, especially the license problem of the module. . Of course, it also gives you the opportunity to make a name for yourself, and you should also be responsible. Your more detailed description of the module will help you debug errors later. Modinfo allows you to identify modules faster. If necessary, please refer to the LDD (<<<Linux Device Drivers>>, hereinafter referred to as LDD) macro description for more MODULE_XXX.

  • Copyright © Windows knowledge All Rights Reserved