The third chapter
This chapter touches on the kernel source code, compiling and debugging the kernel source code
Kernel: The bottom layer of the entire operating system, which is responsible for the entire hardware driver and provides various systems with the required kernel functions. The kernel is essentially a file on the system, which contains the detection program and driver module of the hardware of the driver host. When the system reads BIOS and loads MBRAfter the bootloader is loaded, the kernel can be loaded into memory. Then the kernel starts to detect the hardware, mount the root directory and get the kernel module to drive all the hardware, and then call / SBIN / init to start many of the services needed by the system in sequence.
Qemu :Analog processors that distribute source code with GPL licenses can start Linux programs compiled for different CPUs.
2. Constructing a Simple Linux Kernel
The constructed MenuOS system is integrated by the Linux kernel image and the root file system.
LinuxKernel exists in the form of file on PC (saved as disk file), which is called “image file”. After the kernel compiles, two files are generated, one image and one zImage, where Image is the kernel image file and zImage is the kernel.An image compression file, image is about 4M, while zImage is less than 2M. In order to use the compressed version of zImage, decompression code must be added at the beginning of the zImage before it can be executed, so its execution speed is faster than that of Image.Slow. However, considering that the storage capacity of embedded systems is generally small and the kernel needs to be resident in memory, zImage can occupy less storage space, so it is worthwhile to sacrifice a bit of performance cost. Therefore, compressed kernel image files, or zImage, are commonly used in embedded systems.
The root file system is first and foremost a file system. This file system not only has the function of storing data files in ordinary file system, but also has the special feature compared with ordinary file system. It is the first file system mounted when the kernel starts up, and the image file storage of the kernel code.In the root file system, the system boot initiator loads some initialization scripts (such as rcS, inittab) and services into memory to run after the root file system is mounted. First mount / dev / ram0, then execute / linuxrc. and so on. switchAfter the root file system is executed, that is, at the end of the Start_kernel() function, the process of executing init is the first user process. Various initialization operations are performed on the system.
In the virtual machine in the lab building, you can run the Linux kernel source code and file system by directly entering the Linux Kernel directory with the following commands
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rotes.img
Among them, bzImage is a gzip compressed file of vmlinux, which is suitable for large kernel; vmLinux is the most original ELF file compiled; initrd is a memory root file system, and only one rootfs.img is created.The function of init is to replace init with menu program and enter menu program after the kernel is started.
Tracking and debugging the start-up process of the Linux kernel
Qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rotes.img -s -S
– S CPU before initialization
-s” on TCP 1234 port. The default is to create a gdb-server on tcp::1234 port.
Open another window, start gdb, load the kernel, and establish a connection
file linux-3.18.6/vmlinux #Load in the kernel image with the symbol table
target remote:1234 #Link GDB server with tcp: 1234 port
Then set the endpoint at the start_kernel function and rest_init to debug and run.
4. Analysis of start_kernel() and rest_init()
start_kernel( )Equivalent to main function in main.c, it runs first. Before calling this function, the kernel code is mainly written in assembly language, which is used to initialize the hardware system and set up the environment for the operation of C code. This function mainly initializes each module, trap_iNit () (initialization of interrupt vectors), mm_init () (initialization of memory management) sched_init () (initialization of scheduling module), etc.
init_task() ：0Number process, the starting point of initialization
struct task_struct init_task = INIT_TASK(init_task);
It can be seen that init_task (process 0) is a task_struct type and a process descriptor. It is initialized with macro INIT_TASK, and init_task is the only process that is not generated by fork.
In this function, the kernel_thread process is called to create kernel_init and kthreadd kernel threads
kernel_init()The kernel thread is the No. 1 kernel thread, which is responsible for part of the initialization of the kernel and system configuration. Finally, do_execve is called to load the init program. Finally, the init process evolves into the user-mode No. 1 process.
kthreadd()The task of the function is to manage and schedule other kernel threads, kernel_thread. Run kthread maintained in the kthread_create_list global list in the for loop, in the create_kthread() functionThe kernel_thread is called to generate a new process and is added to the list, so all kernel threads are directly or indirectly kthreadd-parent processes.
This week, I learned the source code of the Linux kernel. I have a better understanding of the source code directory and compilation process of the kernel, but I always encounter new problems in learning, such as the kernel_thread process is fork from init zero, idle process and zero.The relationship between processes and the differences between kernel threads and user processes are mostly solved in CSDN forums, but it is found that the knowledge inside the kernel is very profound and more information needs to be consulted.