Linux kernel interpretation
For a lot of Linux enthusiasts, it is very interested in the kernel, but there is no way, this article aims to introduce an interpretation of Linux kernel source
Getting started by the code, not to explain the complex kernel mechanism of Linux.
1. Core source program document organization
(1) Linux core source program is usually installed under / usr / src / linux, and it has a very simple number
Agreement: Any even core (for example, 2.0.30) is a stable release of the core, and any odd core
(For example, 2.1.42) is a core of development.
Based on stable 2.2.5 source code, the second part of the implementation platform is Redhat Linux 6.0.
(2) The document of the core source program is organized by tree structure, and you will see some purposes in the uppermost layer of the source tree.
record:
● ARCH: The Arch subdirectory includes all core code related to the architecture. Each of its subdirectory
Table A supported architecture, such as the I386 is a subdirectory of Intel CPUs and compatible architectures.
The PC is generally based on this directory;
● Include: The incrude subdirectory includes most of the header files that need to be compiled. Unrelated header file with the platform
In the include / linux subdirectory, the header related to the Intel CPU is in the include / ASM-I386 sub-directory
And the include / SCSI directory is the header file directory for the SCSI device;
● Init: This directory contains the core initialization code (Note: not the system's boot code), contains two files
Main.c and Version.c, this is a very good starting point for studying how the core is working;
● MM: This directory includes all memory management code independent of the CPU architecture, such as page-store management memory
Allocation and release, etc., and the memory management code related to the architecture is located in Arch / * / mm /, such as Arch / I38
6 / mm / fault.c;
● kernel: The main core code, the file in this directory implements the kernel function of most Linux systems,
The most important files are Sched.c, similar, and architectural code in Arch / * / kernel;
● Drivers: Place all device drivers for the system; each driver also occupies a subdirectory, such as / bl
OCK is a block device driver, such as IDE (IDE.c). If you want to see all possible file systems
How is the device initialized, you can see Device_Setup () in drivers / block / genhd.c. It not only
Improve the hard disk and initialize the network because the network is required when installing the NFS file system.
Other library code such as lib placing core; NET, core and network-related code; IPC, this directory contains core
Inter-process communication code; FS, all file system code and various types of file operation code, each of it
The subdirectory supports a file system, such as FAT and EXT2; Scripts, this directory contains scripts for configuring core
Document, etc.
Generally there is a .depend file and a makefile file in each directory, both of these files are compiled
The auxiliary file used, carefully read these two files to clarify the connection and relying on the relationship between the various files.
Help, and in some directory there is a readme file, it is some instructions for files in this directory, equally advantageous
We understand the internal nuclear source code.
2. Interpretation of actual combat: adding a system call for your kernel
Although Linux's core source code is very reasonable, scientifically, the functionally associated files are placed in the same subdirectory, which makes the program more readable. However, Linux's kernel source code is too big and
It is very complicated, even with a very reasonable file organization method, there is still a lot of files in different directories.
Association, part of the code to analyze the core to see several other related files, and may also
Not in the same subdirectory.
The huge complexity of the system is complex, which may be the main reason for many people.
. Of course, this return brought by this daunting labor is also very fascinated: you can not only learn from the middle.
Many of the underlying knowledge of computers (such as booting the system below), experience the entire operating system system
Structure of the structure and the cleverness of the algorithm when solving a specific detail problem, and more importantly, the source code is analyzed.
In the process, you will be specialized in a little bit, and you will be able to make it out; even, as long as you analyze 1/10 code, you will
Will deeply understand that what kind of code is written by a professional programmer, what kind of code is an amateur
Fans written.
In order to make the reader can better experience this feature, the following will give a specific kernel analysis instance, hoping to pass
This example makes the reader some specific understandings for Linux kernel organizations, and readers can learn some inside.
Nuclear analysis method.
The following is the analysis example:
(1) Operation platform
Hardware: CPU Intel Pentium II;
Software: Redhat Linux 6.0; Nuclear Version 2.2.5
(2) Related kernel source code analysis
1 Boot and initialization of the system: There are several ways to guide Linux systems, and there are common LILO, LoadIn
Guide and Linux's bootsect-loader, while the latter's corresponding source program is Arch / I386 / Boot / Bo
Otsect.s, it is a compiler of real models, limited to the space here. No matter which guidance method, the most
Behind you want to jump to the Arch / I386 / Kernel / Setup.s. Setup.s is mainly initialization in time mode,
The system enters the protection mode for preparation. Thereafter, the system performs Arch / I386 / Kernel / Head.s (compressed after compression)
The kernel must first execute Arch / I386 / boot / compressed / head.s); a compilation defined in Head.s
Program setup_idt, it is responsible for establishing a 256 Idt table (Interrupt Descriptor Table), this table
The entry address of all divisions and interrupts are saved, including the system calling the total controller system_call.
site. Of course, in addition to this, Head.s will do some other initialization work.
2 The first kernel program for the system after initialization, ASMLINKAGE VOID __INIT START_KERNEL (VOID)
Definition in /usr/src/linux/init/main.c, it is called USR / SRC / Linux / Arch / I386 / KERNEL
/ TRAPS.C A function void __init trap_init (void) puts the entry of each trap and interrupt service
The port address is set to the IDT table, where the system calling the total controller system_cal is one of the interrupt service programs; VO
ID __INIT TRAP_INIT (VOID) function passes a macro set_system_gate (Syscall_Vector
, & system_call), hung in the inlet of the system calling the total control program on the interrupt 0x80.
Syscall_vector is a constant defined in /usr/src/linux/arch/i386/kernel/irq.h
0x80, and system_call is the entrance address of the interrupt presser program, and the interrupt total control program is defined by assembly language.
In /usr/src/linux/arch/i386/kernel/entry.s.
3 Interrupt General Control Procedure is mainly responsible for saving the status before the processor executes the system call, check whether the current call is legal, and
According to the system call vector, make the processor jump to the corresponding system service routine saved in the sys_call_table table.
The entrance, returning from the system service routine, recovery the processor status returns to the user program.
And system call vector is defined in /usr/src/linux/include/sm-386/unistd.h, sys_call_t
Able table definition in /usr/src/linux/Arch/i386/kernel/entry.s, at the same time / usr / src / L
The user programming interface of the system call is also defined in INUX / INCLUDE / ASM-386 / UNISTD.H.
4 This shows that Linux system calls are also like the INT 21h interrupt service of the DOS system, which interrupts 0x800
As a total entrance, then go to the entry address of various interrupt service routines saved in the sys_call_table table
To form a variety of different interrupt services.
It can be seen from the above source code analysis. To add a system call, you must add one in the sys_call_table table.
And save your own system service routine entry address, then recompile the kernel, of course, system services
The routine is essential.
It can be seen that in this version of the Linux kernel source program <2.2.5>, the source program file related to the system call includes the following
These ones:
* ARCH / I386 / BOOT / BOOTSECT.S
* ARCH / I386 / KERNEL / SETUP.S
* Arch / i386 / boot / compressed / head.s
* ARCH / I386 / KERNEL / Head.s
* nit / main.c
* RCH / I386 / KERNEL / TRAPS.C
* RCH / I386 / KERNEL / ENTRY.S
* RCH / I386 / KERNEL / IRQ.H
* nClude / asm-386 / unistd.h
Of course, this is just a few main files involved. In fact, the file that is increasing the system call is really modified.
INCLUDE / ASM-386 / Unistd.h and Arch / I386 / kernel / entry.s two.
(3) Modification of source code
1 In the addition system service routine in kernel / sys.c is as follows:
ASMLINKAGE INT SYS_ADDTOTAL (Int Numdata)
{
INT i = 0, enddata = 0;
While (i <= numdata)
Enddata = i ;
Return Enddata;
}
This function has an INT type entry parameter NumData, and returns the accumulated value from 0 to NumData, but also
You can put the system service routine in your own defined file or other files, just do it in the corresponding file.
The description of it.
2 Add the entry address of the SMLINKAGE INT SYS_ADDTOTAL (INT) to the SYS_CALL_TABLE table.
The last few line source code in Arch / i386 / kernel / entry.s is modified:
...
.long symbol_name (sys_sendfile)
.long symbol_name (SYS_NI_SYSCALL) / * streams1 * /
.long symbol_name (SYS_NI_SYSCALL) / * streams2 * /
.long symbol_name (sys_vfork) / * 190 * /. Rept NR_SYSCALLS-190
.long symbol_name (SYS_NI_SYSCALL)
.endr
After modification: ... ...
.long symbol_name (sys_sendfile)
.long symbol_name (SYS_NI_SYSCALL) / * streams1 * /
.long symbol_name (SYS_NI_SYSCALL) / * streams2 * /
.long symbol_name (sys_vfork) / * 190 * /
/ * Add by i * /
.long symbol_name (sys_addtotal)
.rept nr_syscalls-191
.long symbol_name (SYS_NI_SYSCALL)
.endr
3 Put the vector corresponding to the added sys_call_table entry, in include / ASM-386 / Unistd.h
It is necessary to declare to query or call for user processes and other system processes.
Added part /usr/src/linux/include/sm-386/unistd.h file is as follows:
...
#define __nr_sendfile 187
#define __nr_getpmsg 188
#define __nr_putpmsg 189
#define __nr_vfork 190
/ * Add by i * /
#define __nr_addtotal 191
4 Test Program (Test.c) is as follows:
#include
#include
_SysCall1 (int, addtotal, int, num)
Main ()
{
INT I, J;
DO
Printf ("Please Input a Number";
While (Scanf ("% D", & I) == EOF);
IF ((j = addtotal (i)) == - 1)
"" Error Occurred in syscall-addtotal (); ");
Printf ("Total from 0 TO% D IS% D", I, J);
}
Compile the new kernel after the revised, and boot it as a new operating system, you can find it after running several programs.
Everything is normal; compile the test program under the new system (Note: This system is not provided due to the original core
With only the new core after compiled, this test program may be compiled by), and the operation is as follows:
$ GCC 杘 Test Test.c
$. / TEST
Please Input a Number
36
Total from 0 to 36 IS 666
It can be seen that the modification is successful, and further analyzes the relevant source code can be seen that in this version of the core, from / usr / src /
The settings of the sys_call_table table can be seen in the Linux / Arch / I386 / kernel / entry.s file.
Several system-called service routines are the same function defined in /usr/src/linux/kernel/sys.c:
ASMLINKAGE INT SYS_NI_SYSCALL (VOID)
{
Return -enosys;
}
This is, for example, Articles 188 and 189.
...
.long symbol_name (sys_sendfile)
.long symbol_name (SYS_NI_SYSCALL) / * streams1 * /
.long symbol_name (SYS_NI_SYSCALL) / * streams2 * /
.long symbol_name (SYS_VFORK) / * 190 * / ... ...
And these two in the file /usr/src/linux/include/sm-386/unistd.h are declared as follows:
...
#define __nr_sendfile 187
#define __nr_getpmsg 188 / * Some People Actual Want Street * /
#define __nr_putpmsg 189 / * Some People Actually Want Street * /
#define __nr_vfork 190
It can be seen that in this version of the kernel source code, since the ASMLINKAGE INT SYS_NI_SYSCALL (VOID) function
Do not do anything, so several system calls, including getPMSG, PUTPMSG are not performed.
Operation, that is, the air conditioner to be expanded; but they still take up the sys_call_table entry, and it is estimated that this is
In order to facilitate the expansion of the system call, the valuers need to increase the corresponding service routines (such as increasing service routines)
GETMSG or PUTPMSG can achieve the role of increasing system calls.
3. Conclude
Of course, for a huge complex Linux, an article is far less enough, and the code related to the system call is only a very small part of the kernel. It is important that the method, master the analysis method, so the above analysis is just a boot Role, and true analysis still needs to be reader.