process - Jokacer/Learn GitHub Wiki

  进程(process)是程序执行时的一个实例,使用进程描述符进行标识,一般存在task_struct结构中,该结构包含该进程的所有信息,例如进程优先级、目前进程状态、分配地址空间、访问文件权限等信息,示意图如下task_struct示意图

  其中thread_info(线程描述符)包含进程的基本信息,在Linux为进程分配存储区域时和内核栈紧凑在一起放入内存中,总共大小为8k即两个页框大小,所以,考虑到效率因素,页框起始地址为213的倍数。

union thread_union{
   struct thread_info thread_info;  //52byte
   unsigned long stack[2048];  //8K
};

  当进程因为中断或系统调用进入内核时,进程使用的堆栈也需要从用户栈到内核栈。进程陷入内核态后,先把用户堆栈的地址保存到内核堆栈中,然后设置设置CPU堆栈寄存器为内核栈的地址,这样就完成了用户栈到内核栈的转换;当进程从内核态恢复到用户态时,把内核中保存的用户态堆栈的地址恢复到堆栈指针寄存器即可。这样就实现了内核栈到用户栈的转换。

进程由用户栈到内核栈转换时,进程的内核栈总是空的。每次从用户态陷入内核时,得到的内核栈都是空的,所以在进程陷入内核时,直接把内核栈顶地址给堆栈指针寄存器即可。

  在进程描述符中state字段和exit_state字段描述进程的当前状态,严格意义上只能设置一种状态,采用宏定义

#define TASK_RUNNING        0  
#define TASK_INTERRUPTIBLE  1  
#define TASK_UNINTERRUPTIBLE    2  
#define __TASK_STOPPED      4  
#define __TASK_TRACED       8  
/* in tsk->exit_state */  
#define EXIT_ZOMBIE     16  
#define EXIT_DEAD       32  
/* in tsk->state again */  
#define TASK_DEAD       64  
#define TASK_WAKEKILL       128  
#define TASK_WAKING     256  

TASK_RUNNING :运行态(RUNNING)或就绪态(READY)。表示进程要么正在执行,要么正要准备执行。
TASK_INTERRUPTIBLE :可中断的等待状态。表示进程被阻塞。能响应信号,直到被唤醒,进程的状态就被设置为 TASK_RUNNING。
TASK_UNINTERRUPTIBLE :不可中断的等待状态。的意义与TASK_INTERRUPTIBLE类似,无法响应信号。该进程等待一个事件的发生或某种系统资源。
__TASK_STOPPED :暂停状态。表示进程被停止执行。
__TASK_TRACED : 跟踪状态。TASK_TRACED状态相当于在TASK_STOPPED之上多了一层保护,处于TASK_TRACED状态的进程不能响应SIGCONT信号而被唤醒。只能等到调试进程通过ptrace系统调用执行PTRACE_CONT、PTRACE_DETACH等操作(通过ptrace系统调用的参数指定操作),或调试进程退出,被调试的进程才能恢复TASK_RUNNING状态。
EXIT_ZOMBIE :僵尸态。此时进程不能被调度,但是PCB(Processing Control Block、进程控制块)未被释放,等待父进程wait4()或者waitpid()系统调用来返回死亡信息。
EXIT_DEAD :死亡态。表示一个已终止的进程,其PCB被释放。

  state字段通常用简单的赋值语句进行设置tsk->state = TASK_RUNNING

进程管理

  采用进程链表对进程进程管理,进程链表是一个双向链表,系统根据进程优先级划分出了140个进程链表以提高调度程序运行的速度,CPU在考虑运行一个新的进程时只需要考虑在TASK_RUNNING状态下的进程。

  在多处理器系统中每个CPU都有自己的运行队列,即进程链表集。

  为了通过进程的PID快速导出对应的进程,采用了四个hash表来对进程id进行管理

Hash表的类型 字段名 说明
PIDTYPE_PID pid 进程的PID
PIDTYPE_TGID tgid 线程组的领头进程的PID
PIDTYPE_PGID pgrp 进程组领头进程的PID
PIDTYPE_SID session 会话领头进程的PID

PID散列表

⚠️ **GitHub.com Fallback** ⚠️