process - Jokacer/Learn GitHub Wiki
进程(
process
)
是程序执行时的一个实例,使用进程描述符进行标识,一般存在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 |