Linux kernel interpretation

xiaoxiao2021-03-06  122

Linux kernel interpretation

锋荣 [This article is provided by "Software Engineers" magazine]

For a lot of Linux enthusiasts, it is interested in the kernel but does not follow the mouth, this article aims to introduce a way to interpret the Linux kernel source code, not to explain the complex kernel mechanism of Linux;

One. Document organization of the core source program 1. The 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 core of stable release, 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 core source program is organized by the tree structure. You will see such a directory in the top of the source tree: ● Arch: Arch subdirectory includes all and architectural related core code. Each subdirectory represents a supported architecture, such as the I386 is a subdirectory for Intel CPUs and compatible architectures. The PC is generally based on this directory; ● Include: Include subdirectory includes most of the header files needed to compile the core. With the platform-independent header files in the include / Linux subdirectory, with the Intel CPU-related header files in the include / ASM-I386 subdirectory, the include / SCSI directory is the header file directory of the SCSI device; ● Init: this The directory contains the core initialization code (Note: not a system boot code), contains two files main.c and version.c, which is a very good starting point for studying how the core works. ● MM: This directory includes all memory management code independent of the CPU architecture, such as page-oriented management memory allocation and release, etc .; and architectural memory management code is located in Arch / * / mm /, such as Arch / I386 / mm / fault.c ● kernel: The main core code, this directory implements most Linux system kernel functions, the most important files are SCHED.C; the same, and the architecture related code ARCH / * / KERNEL; ● Drivers: Place all the device drivers for the system; each driver also occupies a subdirectory: such as / block is a block device driver, such as IDE (IDE.c). If you want to see how all the devices that may contain a file system is initialized, you can see Device_Setup () in drivers / block / genhd.c. It not only initializes the hard disk, but also initializes the network, because the network is required to install the NFS file system: If the network places the core library code; NET, core and network related code; IPC, this directory contains the code between the core process FS, all file system code and various types of file operation code, each subdirectory supports a file system, such as FAT and Ext2; Scripts, this directory contains a script file for configuring the core. Generally, in each directory, there is a .depend file and a Makefile file, both files are compiled auxiliary files, carefully read these two files to clarify the links and relying on each file. It is very helpful; and, in some directory, there is a readme file, it is some instructions on the files in this directory, which is equally conducive to our understanding of the kernel source. Interpretation: Increases a system call for your kernel, though, Linux's kernel source code is very reasonable, scientific, and the files associated with the files are placed in the same subdirectory, which makes the program more readable. .

However, Linux's kernel source code is too big and very complicated, even with a very reasonable file organization method, there is still a lot of associations between files in different directories, and some of the code to analyze the core will usually view other few more. A related file, and may not be in the same subdirectory. The huge complexity of the system is complex, which may be the main reason for many people. Of course, the return brought about by this daunting labor is also very fascinating: you can not only learn from middle school to many computers (as guidance of the system will mention below), experience the entire operation The exquisiteness of the system architecture and the skill of the algorithm; and more importantly, in the analysis process of the source code, you will be able to specialize in a point, and even, as long as After analyzing one quarter code, you will deeply understand that what kind of code is written by a professional programmer, what code is a hobby written. In order to make the reader better experience to this feature, the following will give a specific kernel analysis example, hoping to pass this example, so that the reader has some specific understandings for Linux kernel, from the readers can learn some pairs Analysis method of the kernel. 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. System guidance and initialization: Typical guidance of Linux systems: common LILO, Loadin boot and Linux bootsect-loader, while the source program is Arch / i386 / boot / bootsect. S, it is a confirming program of the real model, limited to the space here; no matter which guidance method, finally jump to the Arch / I386 / kernel / setup.s, setup.s mainly moderate mode Initialization, prepare for the system to enter the protection mode; thereafter, the system performs Arch / I386 / Kernel / Head.s (the kernel stored after compressed "should execute Arch / i386 / boot / compressed / head.s); HEAD. A assembler setup_idt defined in S, it is responsible for establishing a 256 Idt table (Interrupt Descriptor Table), which saves all the inlet addresses of all divisions and interrupts; including the system calling the total controller system_call entry address; Of course, in addition to this, Head.s must do some other initialization; 2. The first kernel program that is running after the system is initialized. ASMLINKAGE VOID __INIT STARNKERNEL (VOID) is defined in /usr/src/linux/init/main.c, which is called USR / SRC / Linux / Arch / I386 / Kernel / Traps. A function void __init trap_init (void) sets the entry address of the respective traps and the interrupt service program to the IDT table, where the system calling the prescriber system_cal is one of the interrupt service programs; void __init trap_init (void) function passes Call a macro set_system_gate (syscall_vector, & system_call); hang the entry of the system calling the total controller on the interrupt 0x80; where syscall_vector is defined in /usr/src/linux/arch/i386/kernel/irq.h in a constant 0x80 , SYSTEM_CALL is the entry address of the interrupting the total control program; the interrupt machin program is defined in /usr/src/linux/Arch/i386/kernel/entry.s with assembly language; 3. Interrupt General control program is mainly responsible for saving processing When the computer is executed, the current call is legal, and the vector is called to the system to jump to the entry of the corresponding system service routine saved in the sys_call_table table; return the processor from the system service routine Status returns the user program; and the system call vector defines in /usr/src/linux/include/ASM-386/unistd.h; sys_call_table table definitions in /usr/src/linux/Arch/i386/kernel/entry.s In /usr/src/linux/include/ASM-386/Unistd.h also defined the user programming interface of the system call; 4. It can be seen that Linux system calls are also like the INT 21H interrupt service in the DOS system. It puts the 0x80 interrupt as a total entry, then goes to the entry address of the various interrupt service routines saved in the sys_call_table table, forming a variety of interrupt services; can be seen from the above source code analysis, to add a system call You must add an item in the sys_call_table table, and save your own system service routine's entry address, Then recompile the kernel, of course, the system service routine is essential. This can be seen in this version of the Linux kernel source program <2.2.

5> The source program file related to the system call includes the following: 1. Arch / i386 / boot / bootsect.s2. Arch / i386 / kernel / setup.s3. Arch / i386 / boot / compressed / head.s4. Arch / i386 / kernel / head.s5. INIT / main.c6. Arch / i386 / kernel / traps.c7. Arch / i386 / kernel / entry.s8. Arch / i386 / kernel / Irq.h9. INCLUDE / ASM-386 / Unistd.h is of course, which is just a few main files involved. In fact, increasing system calls really want to modify file only include both include / ASM-386 / UNISTD.H and Arch / I386 / Kernel / Entry.s;

[3] Modification to the kernel source 1. Increase the system service routine in kernel / sys.c 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; of course, it can also put the system service routine in a file or other file, just to correspond The file is necessary for the file; 2. Add the entry address of the ASMLINKAGE INT SYS_ADDTOTAL (INT) to the sys_call_table table: the last few line source code in Arch / i386 / kernel / entry is: ... .. . .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 modified to: ... ... .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) .endr3. Put the added sys_call_table entry. Vector in Include The necessary declarations in /ASM-386/unistd.h for user processes and other system processes inquiry or call: Added part /usr/src/linux/include/sm-386/unistd.h files are as follows: .. . ... #define __NR_sendfile 187 #define __NR_getpmsg 188 #define __NR_putpmsg 189 #define __NR_vfork 190 / * add by I * / #define __NR_addtotal 1914. test procedure (test.c) as follows: #include # include_syscall1 (int, addtotal, Int, Num)

Main () {Int i, j; do printf ("please input a number / n"); while ("% D", & i) == EOF); ​​if ((j = addtotal (i)) == -1) Printf ("Error Occurred in syscall-addtotal (); / n"); Printf ("Total from 0 to% D IS% D / N", I, J);} For the new core kernel Compile, and guide it as a new operating system. After running a few programs, you can find everything is normal; compile the test program under the new system (* Note: Due to the original core, this system is not provided, only after compiling Under the new kernel, this test program can be compiled), the operation is as follows: $ gcc -o test test.c $. / Testplease Input a Number36Total from 0 to 36 IS 666 visible, successful modification; and related source code Further analysis can be seen that in this version of the kernel, the settings of the SYS_CALL_TABLE table can be seen from the /usr/src/linux/Arch/i386/kerneel/entry.s file, there are several system calls for service routines. Is the same function defined in /usr/src/linux/kernel/sys.c: Asmlinkage Int sys_ni_syscall (void) {return -enosys;} For example, Article 188 and 189 items: ... ... .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 * / ... ... in which two Document /usR/src/linux/include/src/linux/include/ASM-386/Unistd.h is declared as follows: ... # Define __nr_sendfile 187 # define __nr_getpmsg 188 / * Some People Actually W Ant streams * / # define __nr_putpmsg 189 / * Some people __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 does not perform any operation, Several system calls in GetPMSG, Putpmsg are not performed, 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 the designer arranged in order to facilitate the expansion of the system; So just increase the corresponding service routines (such as adding service routines getMSG or PUTPMSG) to increase the role of the system call. Conclusion: Of course, for a huge complex Linux kernel, an article is far less, and the code related to the system call is only a very small part of the kernel; but the important method, master the method; The analysis is just a role of guidance, and the true analysis is to wait for the reader's own efforts. China Linux Forum Copyright

转载请注明原文地址:https://www.9cbs.com/read-99094.html

New Post(0)