当前位置: 首页 > 科技观察

Linux内核进程管理基础

时间:2023-03-19 14:32:38 科技观察

本文转载自微信公众号《人人都是极客》,作者为布道师Peter。转载本文请联系大家是极客公众号。废话不多说,内存管理暂时告一段落,正式进入进程管理的内容。内核通过task_struct来描述进程。使用命令pstree可以让内核以树状结构列出进程之间的关系,如下图所示:这是进程在内核中的结构,那么内核是如何以树状结构来管理和描述这些的呢?过程呢?用来描述进程的数据结构可以理解为进程的属性。比如进程的状态,进程标识符(PID)等,都封装在进程描述符task_struct这个数据结构中。structtask_struct{....../*-1unrunnable,0runnable,>0stopped:*///任务状态。<0未运行,=0正在运行,>0已停止。volatilelongstate;......//指向内核栈的指针void*stack;....../*进程的调度策略,有6种。*Deadline进程调度策略:SCHED_DEADLINE。*实时进程调度策略:SCHED_FIFO、SCHED_RR。*普通进程调度策略:SCHED_NORMAL、SCHED_BATCH、SCHED_IDLE。*/unsignedintpolicy;...//进程内存管理信息structmm_struct*mm;structmm_struct*active_mm;...//进程标识符,用来表示一个进程pid_tpid;...//线程列表structlist_headthread_group;structlist_headthread_node;structcompletion*vfork_done;....../*Filesysteminformation:*///文件系统信息structfs_struct*fs;/*Openfileinformation:*///打开文件信息structfiles_struct*files;....../*CPU-specificstateofthistask:*///进程的CPU状态,切换时要保存到停止进程的task_struct中structthread_structthread;...};内核是利用list_head链表对shape结构管理的各个进程的关系进行树化。task_struct结构体内容太多,这里只列出部分成员变量。有兴趣的读者可以去源码中的include/linux/sched.h头文件查看。task_struct中的主要信息类:Identifier:描述本进程的唯一标识pid,用于区分其他进程。Status:任务状态、退出代码、退出信号等。Priority:相对于其他进程的优先级ProgramCounter:程序中下一条要执行的指令的地址MemoryPointer:包括程序代码和进程相关数据的指针,以及与其他进程共享内存块的指针上下文数据:进程执行过程中处理器寄存器中的数据I/O状态信息:包括显示的I/O请求、分配的进程I/O设备、进程使用的文件列表记录账户信息:可能包括totalprocessortime,totalclockused,timelimit,accountnumber等ARM64不需要获取当前task_structstatic__always_inlinestructtask_struct*get_current(void){unsignedlongsp_el0;asm("mrs%0,sp_el0":"=r"(sp_el0));return(structtask_struct*)sp_el0;}#definecurrentget_current()可以看出sp_el0直接作为task_struct返回了。对于ARM64平台,使用sp0_el1寄存器记录当前进程的task_struct地址。当内核进行进程切换时,会将当前运行进程的task_struct地址记录到这个寄存器中。所以,我们要为current找到task_struct也很简单,不再需要通过sp和thread_info来定位。volatilelongstate-1未运行,=0为运行状态,>0为停止状态,Linux中ready和running对应TASK_RUNNING标志,ready表示进程在队列中,未被调度;runningis表示进程正在CPU上运行;void*stack是指向内核栈的指针,内核通过dup_task_struct为每个进程分配内核栈空间,并记录在这里。structmm_struct*mm进程地址空间相关信息。task_struct的分配和初始化图可以看出,上层应用程序通过各种方式创建进程时,最终都会通过_do_fork创建一个新的task_struct。