Description
Preliminary knowledge
CPU-Bound task design
Loop root sign : It does not need to access disk and memory, and is a computationally intensive task.
long count=__LONG_MAX__; for (long i = 0; i < count; i++) { if(i%10000==0) printf("%ld\n", i); sqrt(100000000001.0); } printf("Done.\n"); return 0;
Set process priority
On startup: nice
nice -n <Priority> <Command>
CPU bound
-
View the CPUs that can run a process
taskset -c -p <PID>
-
Bind a process to a (set of) CPUs at startup
taskset -c <CPU_List_,_Sep> <Command>
Experimental process and results
The first part of task 1 uses the following script to start ten processes: set the nice value of 5 processes to 0, and the nice value of 5 processes to 4, and these 10 processes are all bound to logical cores 11
.
#!/bin/bash gcc -o task1 task1.c if [ $? -eq 0 ]; then for i in {1..5} do nice -n 0 taskset -c 11 ./task1 & done for i in {6..10} do nice -n 4 taskset -c 11 ./task1 & done fi
Use htop
the command to get the following results
-s Command
It can be seen that the five processes with a nice value of 0 occupy about 70% of the CPU, and the five processes with a nice value of 4 occupy about 30% of the CPU.
Create a real-time process using the following command
nice -n -20 taskset -c 11 ./task1 &
The result is as follows:
It can be seen that the real-time process occupies most of the CPU resources.
Task 2
process management
The kernel stores the list of processes in the bidirectional circular linked list of the task queue. The type of each node of the linked list is a process descriptor task_struct
structure, which is defined in linux/sched.h
the file. The process descriptor contains all the information of the process, so ctx
the attributes to be implemented in task 2 should be added in task_struct
.
User-defined content is best added task_struct
in the recommended area of the page .
process creation
The process creation of Linux is decomposed into fork()
two exec()
functions- fork()
creating a child process by copying the current process, exec()
reading the executable file and loading it into the address space to start running. Linux clone()
is implemented through system calls fork()
, clone()
and the call copy_process()
completes the work of copying the parent process and creating a child process. copy_process()
It is called when the process is created and is defined in kernel/fork.c
. Task 2 needs to be initialized in this function ctx
.
process scheduling
Functions in Linux schedule()
are responsible for process scheduling. schedule()
The function execution pick_next_task()
function selects the process that should be scheduled most. In other words, when a process is pick_next_task()
selected by a function, it will be scheduled, so it needs to pick_next_task()
be executed before the function returns ctx++
. schedule()
and pick_next_task()
are both defined in kernel/sched/core.c
.
File system directory creation
Directory entries for the file system are fs/proc/base.c
“registered” in, specifically in an array tgid_base_stuff[]
, the type of the array elements is pid_entry
. The “registration” method is shown in the figure, ONE
which is a macro defined by Linux, which means that the file to be registered ( DIR
represents a folder). ctx
Is the file name, S_IRUGO
indicating that it can be read by all users, but the file permissions cannot be changed, proc_tgid_ctx
and it is the corresponding function, which ctx
is executed when it is read.
Compile the kernel
Kernel compilation mainly refers to How To Compile And Install Kernel On Ubuntu , and the problems encountered are detailed in the experience section.
Result analysis
The calculation-intensive application defined in Task 1 is executed in the test.
Access the process /proc/<PID>/ctx
file to see the number of times the process was scheduled.
experience
My biggest experience through this project is that my understanding of the design and implementation of Linux has been greatly improved. This is the first time I have read such a huge underlying code project. Compared with the design ideas learned in class, the complexity of the code made me confused at first.
For this reason, I read the corresponding chapters of the book “Linux Kernel Design and Implementation” in detail, and combined with the kernel source code to understand. This project allowed me to master all kinds of abstract content learned in the “Operating System” course, which is a rare and valuable project experience.
In fact, the biggest difficulty for me in this practice is the compilation and installation of the Linux kernel. Since I directly tried to install on the host Linux system, the host system faced direct interaction with various device drivers, and I may have made many changes to the kernel module later in my long-term use, so the kernel compilation encountered many problems.
The problem during the compilation process is mainly CONFIG_X86_X32
and CONFIG_DEBUG_INFO_BTF
the lack of corresponding support, which must be set n
. The bigger problem occurred during the installation phase, because the new kernel could not read the SSD due to the lack of corresponding modules.
After struggling with the ash shell, changing the uuid of the linux boot hard disk, and changing the SATA compatibility of the BIOS, the practice was completed on the newly created virtual machine. But this process greatly increased my understanding of the machine startup process.