Article Directory
-
- How to read the kernel code efficiently
- 1 Find the driving entry point (the mountain has a small mouth, as if there is light)
- 2 clarify the main context (will be the top of the Ling Ling, a glance at the small mountains)
- 3 In-depth specific functions (the creek returns to the valley, and there is no road, suddenly there are one or two plum blossoms)
How to read the kernel code efficiently
To a large extent, kernel development is not a process of reinventing the "wheel", but to deeply understand and reuse the existing kernel design framework as much as possible, and then refer to similar functional modules to add or rewrite a required function. Only after the overall framework of the core and certain subsystems have been integrated, we can stand on the shoulders of giants to improve the framework itself and achieve independent innovation. If you overemphasize unnecessary "independent innovation", it may make the maintainability of the kernel worse, and the end result will not be worth the loss.
So this time I will share it around how to efficiently read the kernel driver code:
1 Find the driving entry point (the mountain has a small mouth, as if there is light)
If the forest is full of water, there will be a mountain, and the mountain has a small mouth, as if there is light
1.1 Device driver entrance
Reading the kernel driver code first is to find its shiny entry function. Take a relatively independent kernel module as an example. In most cases, if the name of modname
the module is , then the entry function of the module is modname_init()
. The entry function of the module is generally used module_init(modname_init)
for declaration.
#define module_init(x) __initcall(x); //include/linux/init.h
1.2 Subsystem entrance
After the analysis of the kernel options is completed, the initialization of each subsystem enters the second part-the call of the entry function. Generally, subsystems such as USB and PCI will have an subsys_initcall
entry named , if you choose them as the entry point for studying the kernel, then please find it first.
1.3 So where is the entrance of the kernel itself?
The initial entry (the first entry) is architecture-related, in the assembly language code;
while the general entry (the second entry) is architecture-independent, and it is actually init/main.c
inside in the C language. start_kernel()
This do_initcalls()
is the function we need to look for. , Execute all module_init()
functions declared in this function
start_kernel
-> rest_init();
-> kernel_thread(kernel_init, NULL, CLONE_FS);
-> kernel_init()
-> kernel_init_freeable();
-> do_basic_setup();
-> do_initcalls();
2 clarify the main context (will be the top of the Ling Ling, a glance at the small mountains)
We need to be able to sort out the initial frame when we initialize the function.
For example, MMC
in the initialization of the subsystem, the code is like a tree. We need to find the trunk first, then figure out how many branches there are on the trunk, and then look for meaningful leaves on a branch of interest, instead of just encountering one. The root branch, we hurried in to find out all the leaves, when the latter we will fall into the confusion of "not knowing the true face of Mount Lu, only by being in this mountain", our pursuit is "being the top of the mountain, seeing everyone "Small mountains" are transparent.
- Bus, device, driver
In development, we don't really write a bus model. If we focus on specific functions, then we need to focus on the probe
content of peripheral-driven business functions that we do in the development.
entity | Features |
---|---|
equipment | Describe the base address, interrupt number, clock, DMA, reset and other information |
drive | Complete peripheral functions, such as network card receiving and sending packets, sound card recording and playback, SD card reading and writing... |
bus | Complete the association of the device and the driver |
Then the matching process of the three of them is not the focus of development, we can study in the future, and the focus is still to analyze probe
.
Let's take a look at the matching process first, and we can see the complexity of the matching:
3 In-depth specific functions (the creek returns to the valley, and there is no road, suddenly there are one or two plum blossoms)
The gentle and tortuous streams (driving function) linger in the valley (the inner core). I was worried that there was no way forward (the road of development), and suddenly I saw one or two plum blossoms in full bloom (harvest) ahead.
Here we need to focus on what we want to study;
Take MMC as an example:
The functions we need to focus on are:
- Insertion detection
- Reset
- Type detection
- Voltage verification
- CID acquisition
- Wait