进程与进程调度
一、task_struct结构分析
1、进程和程序
所谓进程是由正文段(Text)、用户数据段(User Segment)以及系统数据段(System Segment)共同组成的一个执行环境。
程序只是一个普通文件,是一个机器代码指令和数据的集合,这些指令和数据存储在的一个可执行映像中。程序和进程的组成结构如下:
程序装入内存后就可以运行:在指令指针寄存器的控制下,不断地将指令取至CPU运行。进程是一个动态实体。
2、Linux系统中进程基础
Linux中的每个进程由一个task_struct数据结构来描述,任务(task)和进程(Process )是两个不同概述,task_struct其实就是通常所说的“进程控制块”即PCB。task_struct容纳一个进程的所有信息,是系统对进程进行控制的唯一手段。
3、进程状态(state)
进程执行时,它会根据具体情况改变状态,进程状态是调度和对换的依据。Linux进程主要状态如下:
TASK_RUNNING 可运行
TASK_INTERRUPTIBLE 可中断的等待状态
TASK_UNINTERRUPTIBLE 不可中断的等待状态
TASK_ZOMBIE 僵死
TASK_STOPPED 暂停
TASK_SWaPPING 换入/换出
可运行状态处于这种进程,要么正在运行、要么正准备运行。
等待状态处于该状态的进程正在等待某个事件或某个资源,它肯定位于系统中某个等待队列中。
暂停状态此时的进程暂时停止运行来接受某种特殊处理。
僵死状态进程跃然已经终止,但由于某种原因,父进程还没有执行wait()系统,终止进程的信息也没有回收。
4、进程调度
调度程序来决定系统中哪个进程最应该去运行,并结合进程的状态信息保证系统运转的公平和高效。
进程调度信息如下:
Nice 静态优先级
need_resched 调度标志
Counter 动态优先级
Policy 调度策略
rt_priority 实时优先级
进程调度策略如下:
SCHED_OTHER 其它调度–>适用范围为普通进程
SCHED_FIFO 先来先服务调度–>适用范围为实时进程
SCHED_RR时间片轮转调度–>适用范围为实时进程
只有root用户能通过sched_setscheduler()系统调用来改变调度策略。
5、常用标识符(Identifiers)
每个进程有进程标识符、用户标识符、组标识符。Linux允许最大PID编号为32767,当内核在系统中创建第32768个进程时,就必须重新开始使用已闲置PID编号。
各种各样标识符如下:
pid 进程标识符
uid gid 用户标识符 组标识符
euid egid 有效用户标识符 有效组标识符
suid sgid 备份用户标识符 备份组标识符
f>suid fsgid 文件系统用户标识符 文件系统组标识符
task_struct结构在内存的存放与内核栈是不能分开。
进程内核栈:每个进程都有自己的内核栈,当进程从用户态进入内核态时,CPU就自动地设备该进程的内核栈,也就讲,CPU从任务状态段TSS中装入内核栈指针ESP。比如X86内核
栈的分布如下:
内核栈占用8KB的内存区。实际进程task_struct结构所占的内存是由内核动态分配的,正准确来说,内核根本不给task_struct分配内存,而仅仅给内核栈分配8KB的内存,并把其中一部分给task_struct使用。内核栈大小不能超过7KB,否则,内核栈会覆盖task_struct结构,从而导致内核崩溃。
二、进程组织方式
Linux采用如下几种组织方式:
哈希表如下:
双向循环链表如下:
哈希表主要作用根据进程的pid可以快速地找到对应的进程,但它没有反映进程创建的顺序,也无法反映进程之间的亲属关系,所以引入双向循环链表。每个进程task_struct结构中的prev_task/next_task域用来实现这种链表
运行队列(双向循环队列)如下:
关注我们:
知柯信息安全