linux内核管理学习(Linux内核进程管理之基础)
linux内核管理学习(Linux内核进程管理之基础)-1是不运行的,=0是运行状态,>0是停止状态static __always_inline struct task_struct *get_current(void) { unsigned long sp_el0; asm ("mrs %0 sp_el0" : "=r" (sp_el0)); return (struct task_struct *)sp_el0; } #define current get_current() 可以看出 sp_el0 直接作为 task_struct 返回了。对于ARM64平台,记录当前进程的task_struct地址是利用sp0_el1寄存器,当内核执行进程切换时会把当前要运行的进程task_struct地址记录到该寄存器中。因此我们current查找task
内核通过 task_struct 描述进程用命令 pstree 可以让内核以树形的结构把进程之间的关系列出来,如下图:
这是进程在内核中的结构形式,那么内核是如何来以树形结构管理描述这些进程的呢?用来描述进程的数据结构,可以理解为进程的属性。比如进程的状态、进程的标识(PID)等,都被封装在了进程描述符 task_struct 这个数据结构中。
struct task_struct {
......
/* -1 unrunnable 0 runnable >0 stopped: */
//任务状态。<0是不运行状态,=0是运行状态,>0是停止状态。
volatile long state;
......
//指向内核栈的指针
void *stack;
......
/*进程的调度策略 有6种。
*限期进程调度策略:SCHED_DEADLINE。
*实时进程调度策略:SCHED_FIFO,SCHED_RR。
*普通进程调度策略:SCHED_NORMAL,SCHED_BATCH,SCHED_IDLE。
*/
unsigned int policy;
......
//进程内存管理信息
struct mm_struct *mm;
struct mm_struct *active_mm;
......
//进程标识符 用来代表一个进程
pid_t pid;
......
//线程链表
struct list_head thread_group;
struct list_head thread_node;
struct completion *vfork_done;
......
/* Filesystem information: */
//文件系统信息
struct fs_struct *fs;
/* Open file information: */
//打开文件信息
struct files_struct *files;
......
/* CPU-specific state of this task: */
//进程的CPU状态,切换时,要保存到停止进程的task_struct中
struct thread_struct thread;
......
};
内核就是通过list_head链表把各个进程关系以树形结构管理起来的。
task_struct 结构体内容太多,这里只列出部分成员变量,感兴趣的读者可以去源码 include/linux/sched.h头文件查看。
task_struct 中的主要信息分类:
- 标示符:描述本进程的唯一标识符 pid,用来区别其他进程。
- 状态:任务状态,退出代码,退出信号等
- 优先级:相对于其他进程的优先级
- 程序计数器:程序中即将被执行的下一条指令的地址
- 内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
- 上下文数据:进程执行时处理器的寄存器中的数据
- I/O状态信息:包括显示的I/O请求,分配的进程I/O设备和进程使用的文件列表
- 记账信息:可能包括处理器时间总和,使用的时钟总和,时间限制,记帐号等
更多Linux内核视频教程文档资料免费领取后台私信【内核】自行获取.
Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈-学习视频教程-腾讯课堂
- ARM64不用通过struct thread_info thread_info获取当前task_struct
static __always_inline struct task_struct *get_current(void)
{
unsigned long sp_el0;
asm ("mrs %0 sp_el0" : "=r" (sp_el0));
return (struct task_struct *)sp_el0;
}
#define current get_current()
可以看出 sp_el0 直接作为 task_struct 返回了。对于ARM64平台,记录当前进程的task_struct地址是利用sp0_el1寄存器,当内核执行进程切换时会把当前要运行的进程task_struct地址记录到该寄存器中。因此我们current查找task_struct时也是很简单了,不再用通过sp和thread_info去定位了。
- volatile long state
-1是不运行的,=0是运行状态,>0是停止状态
Linux中的 ready 和 running 对应的都是TASK_RUNNING标志位,ready 表示进程正处在队列中,尚未被调度;running 则表示进程正在CPU上运行;
- void *stack
指向内核栈的指针,内核通过 dup_task_struct 为每个进程都分配内核栈空间,并记录在此。
- struct mm_struct *mm
与进程地址空间相关的信息。
task_struct 的分配和初始化
图中可知,上层应用通过各种方式创建进程时,最终都会通过 _do_fork 新建一个 task_struct。