For a lot of Linux enthusiasts, it is interested in the core, this article is intended to introduce a introductory method to interpret the Linux kernel source code, not to explain the complex kernel mechanism of Linux; 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 device drivers for the system; each driver also occupies a subdirectory: If / 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 interrupt presser program; the interrupt total control program is defined in /usr/src/linux/Arch/i386/kernel/entry.s; 3. Interrupt General Control Program is mainly responsible for saving processing When the computer is executed before the system call, check if the current call is legal, and the system is called to the processor to jump to the portal 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/sm-386/unistd.h also defined the user programming interface of the system call; 4. This shows 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 One item must be added to the sys_call_table table and save your own system service routine's entry address, and 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, and the source program file associated with the system call includes the following: 1. Arch / i386 / boot / bootsect.s 2. Arch / i386 / kernel / setup.s 3. Arch / i386 / boot / compressed / head.s 4. Arch / i386 / kernel / head.s 5. INIT / main.c 6. Arch / i386 / kernel / traps.c 7. Arch / i386 / kernel / entry.s 8. Arch / i386 / kernel / Irq.h 9. INCLUDE / ASM-386 / Unistd.h is of course, which is just a few main files involved.
In fact, increasing system call truly to modify file only two and Arch / i386 / kernel / entry.s; [3] Modification to the kernel source code: 1. In Kernel / Sys. Increase the system service routines in 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 portfolio Numdata And return from 0 to Numdata's accumulated value; of course, you can also put the system service routine in your own defined file or other file, just as necessary in the corresponding file; 2. Put the ASMLINKAGE INT SYS_ADDTOAL (int The entry address is added to the SYS_CALL_TABLE table: the last few line source code in Arch / I386 / KERNEL / ENTRY.S is: ... .long symbol_name (sys_sendfile) .long symbol_name (sys_ni_syscall) / * after 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 as: ... ... .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 added sys_call_table entry to include / A SM-386 / UnisTd.h is necessary to declare for user processes and other system processes or calls: 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 procedure (test.c) as follows: #include #include _syscall1 (int, addtotal , INT, NUM) Main () {INT I, J; Do Printf ("please input a number / n"); while (scanf ("% 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);} After the modification The new kernel is compiled and guides it as a new operating system. After running several programs, you can find everything is normal; compile the test program under the new system (* Note:
Since the kernel is not provided, this test program can be compiled only if the compiled new kernel is possible, the operation is as follows: $ gcc -o test test.c $. / Test please input a Number 36 Total from 0 to 36 IS 666 visible, successful modification; and further analyzing the relevant source code, in this version of the kernel, from /usr/src/linux/arch/i386/kernel/entry.s file The setting of the SYS_CALL_TABLE table can be seen that there are several system calls to the server that are defined in /usr/src/linux/kernel/sys.c: asmlinkage int ss_ni_syscall (void) {return -enosys; item 188, for example} and 189 is so: ... ... .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 * / ... This is the following in the file /usr/src/linux/include/ASM-386/unistd.h, it is declared as follows: ... #define __nr_sendfile 187 #define __NR_getpmsg 188 / * some people actually want streams * / #define __NR_putpmsg 189 / * some people actually want streams * / #define __NR_vfork 190 Thus, in this version of the source code of the kernel, since asmlinkage int sys_ni_syscall (void) The function does not perform any operation, so several system calls, including getPMSG, Putpmsg are not any 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 designer. To facilitate the expansion of the system call; so you only need to increase the corresponding service routine (such as adding service routines getMSG or PUTPMSG). It can achieve the role of increasing system calls. 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. :) Have time to go to our station patching heroes www.patching.Net computer is a skillful hacker who can master only by book and you can get up.