Let's practice printing process descriptor task_ Fields in struct
The method used here is to insert the kernel module, and the method used is to traverse the process linked list
1, Task_ A preliminary interpretation of struct
First, download your own source code. You can refer to my previous blog https://blog.csdn.net/weixin_45730790/article/details/121294180?spm=1001.2014.3001.5501
have access to bootlin View source code online
Open the header file in the directory of the include file. task_ The struct structure is located in the sched. H header file/ include/linux/sched.h
schde.h shows the full picture of pcb in the kernel. There are many fields involved. Here we only focus on the pcb itself, and some fields that can reflect its structure.
First, look at the first field state, that is, its status information,
Next is its kernel stack * stack
flags is the flag of the process
The ptrace field is used to implement breakpoint debugging
Further down, we can see some priority information
prio is dynamic priority, static_prio is static priority, rt_priority is the real-time priority
Next, you can see the policy field, which is its process scheduling policy
Next, you can see the running information sched of the scheduler statistical process_ Info, which is also a structure
Next is the tasks field, which is a two-way linked list. It is this field that connects all processes together so that we can traverse the process.
Next is all the information of its linear address
active_mm is the last accessed address space pointer
Here is the kinship of the process
Print important information of pcb, such as status information, priority information, kinship, file system information and memory information.
These two information are used to reflect the number of context switches. nvcsw reflects the number of active context switches and nivcsw reflects the number of passive context switches
These two fields are used to record missing page statistics
This array is the name of the corresponding program
These two fields are responsible for the communication between the corresponding processes
Here is very important, its file information. fs stores a pointer to the file system information, and files stores a pointer to the process file descriptor table
Next is its namespace
Further down, we can see that this is its signal descriptor
Further down, we can see that IRQ is its interrupt information
Memory recycling
Record the IO count of the process
There are many fields in the back. You can view the blog in more detail https://blog.csdn.net/gatieme/article/details/51383272
2, Write kernel module print task_struct important fields
Here we print important attribute information of pcb, such as status information, process identifier, priority information, kinship, file system information and memory information.
task_struct.c:
#include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #Include < Linux / sched. H > / / task structure #include <linux/fdtable.h> //files #include <linux/fs_struct.h> //fs #include <linux/mm_ Types. H > / / print memory information #include <linux/init_task.h> #include <linux/types.h> #include <linux/atomic.h> MODULE_LICENSE("GPL"); //licence //Entry function static int __init print_pcb(void) //The init macro is supported by the init.h file { struct task_struct *task,*p; struct list_head *pos; //Bidirectional linked list int count=0; //Count the total number of current system processes printk("begin...\n"); //When traversing the linked list, you want to start with the first one task=&init_task; //Point to process pcb 0 list_for_each(pos,&task->tasks) //The traversal operation uses pos to point, and the passed in parameter task points to the tasks field. The tasks of process 0 are traversed. Tasks connect all processes together. { p=list_entry(pos,struct task_struct,tasks); //If you find a node, you can use the tasks field of the node to find the exit address of the structure. The corresponding field tasks //At this point, the p pointer already points to task_ The head of the struct structure, which can be operated by the p pointer count++; //Find a process and add it yourself printk("\n\n"); printk("pid: %d; state: %d; prior: %d; static_pri: %d; parent_pid: %d; count: %d; umask: %d",p->pid,p->__state,p->prio,p->static_prio,(p->parent)->pid,atomic_read(&(p->files)->count),(p->fs)->umask); //In linux, the mm of the kernel thread is empty. If you want to print it, there will be an error and pointer error if((p->mm)!=NULL) printk("Total_vm: %ld",(p->mm)->total_vm); //Total pages in linear area } printk("Number of processes:%d\n",count); return 0; } static void __exit exit_pcb(void) //Exit function { printk("Exiting...\n"); } // Specify the entry point and exit point. The entry / exit point is supported by module.h module_init(print_pcb); module_exit(exit_pcb);
Makefile files are as follows:
#Makefile file note: if the previous. c file is named first.c, then the. o file in the makefile file here #The module should be named first.o. only the root user can load and unload the module obj-m:=task_struct.o #Generate task_ Object file of struct module #The object file should be the same as the module name CURRENT_PATH:=$(shell pwd) #Current path of the module LINUX_KERNEL:=$(shell uname -r) #Current version of linux kernel code LINUX_KERNEL_PATH:=/home/shupeiyao/linux-5.14.17 all: make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules #Compilation module #[Tab] the path of the kernel where the current directory is compiled indicates that the kernel module is compiled clean: make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean #Cleaning module
make compilation
sudo insmod task_struct.ko loading kernel modules
dmesg viewing kernel print information
Some do not print total_vm, indicating that its mm field is empty, which is a kernel thread
There are 361 threads in total
The above is to print tasks in the Linux kernel_ The contents of important fields in struct structure
If it helps you, please like it, pay attention to it or collect it~