一、Linux 内核如何描述一个进程? 目的: 初步了解进程描述符 task_struct。 目录: Linux 的进程 Linux 的进程描述符 task_struct 内核如何找到 task_struct task_struct 的分配和初始化 实验:打印 task_struct / thread_info / kernel mode stack 环境: Linux-4.14 + ARMv7 1. Linux 的进程 进程的术语是 process,是 Linux 最基础的抽象,另一个基础抽象是文件。 最简单的理解,进程就是执行中 (executing, 不等于running) 的程序。 更准确一点的理解,进程包括执行中的程序以及相关的资源 (包括cpu状态、打开的文件、挂起的信号、tty、内存地址空间等)。 一种简洁的说法:进程 = n*执行流 + 资源,n>=1。 Linux 进程的特点: 通过系统调用 fork() 创建进程,fork() 会复制现有进程来创建一个全新的进程。 内核里,并不严格区分进程和线程。 从内核的角度看,调度单位是线程 (即执行流)。可以把线程看做是进程里的一条执行流,1个进程里可以有1个或者多个线程。 内核里,常把进程称为 task 或者 thread,这样描述更准确,因为许多进程就只有1条执行流。 内核通过轻量级进程 (lightweight process) 来支持多线程。1个轻量级进程就对应1个线程,轻量级进程之间可以共享打开的文件、地址空间等资源。 2. Linux 的进程描述符 2.1 task_struct 内核里,通过 task_struct 结构体来描述一个进程,称为进程描述符 (process descriptor),它保存着支撑一个进程正常运行的所有信息。 每一个进程,即便是轻量级进程(即线程),都有1个 task_struct。 sched.h (include\linux)struct task_struct { struct thread_info thread_info; volatile long state; void *stack; [...] struct mm_struct *mm; [...] pid_t pid; [...] struct task_struct *parent; [...] char comm[TASK_COMM_LEN]; [...] struct files_struct *files; [...] struct signal_struct *signal;} 这是一个庞大的结构体,不仅有许多进程相关的基础字段,还有许多指向其他数据结构的指针。 它包含的字段能完整地描述一个正在执行的程序,包括 cpu 状态、打开的文件、地址空间、挂起的信号、进程状态等。 点击查看大图 作为初学者,先简单地了解部分字段就好:: struct thread_info thread_info: 进程底层信息,平台相关,下面会详细描述。 long state: 进程当前的状态,下面是几个比较重要的进程状态以及它们之间的转换流程。 点击查看大图 void *stack: 指向进程内核栈,下面会解释。 struct mm_struct *mm: 与进程地址空间相关的信息都保存在一个叫内存描述符 (memory descriptor) 的结构体 (mm_struct) 中。 点击查看大图 pid_t pid: 进程标识符,本质就是一个数字,是用户空间引用进程的唯一标识。 struct task_struct *parent: 父进程的 task_struct。 char comm[TASK_COMM_LEN]: 进程的名称。 struct files_struct *files: 打开的文件表。 struct signal_struct *signal: 信号处理相关。…