进程的内存映像
Linux下C程序生成主要由四个步骤组成:
- 预编译
- 编译
- 汇编
- 链接
编译器gcc经过预编译,编译,汇编三个步骤将源程序文件转换成目标文件。
如果程序有多个目标文件或程序中使用了库函数,则编译器还需要将所有目标文件及所需的库文件链接起来,最后生成可执行程序。
当程序执行时,操作系统可将可执行程序复制到内存中.
程序转为进程通常需要以下步骤:
- 内核将程序读入内存,为程序分配内存空间
- 内核为该进程保存PID及相应的状态信息,把进城放到运行队列中等待执行。程序转化为进城后就可被操作系统的调度程序执行了。
进程的内存映像是指内核在内存中如何存放可执行程序文件。
在将程序转化为进程的过程中,操作系统将可执行程序从硬盘复制到内存中,其布局如下:
进程映像的位置依赖于使用的内存管理方案。
可执行程序与进程内存映像的不同之处在于:
- 可执行程序位于磁盘中而内存映像位于内存
- 可执行程序没有堆栈,因为程序被加载到内存中才会分配堆栈
- 可执行程序虽然也有未初始化数据段但他并不被存储在位于硬盘中的可执行文件中。
- 可执行程序是静态的,不变的,而内存映像随着程序的执行是在动态变化的,比如数据段随着程序的执行要存储新的变量值,栈在函数调用时也是在不断变化的。
进程与程序的区别:
(1)程序是永存的;进程是暂时的,是程序在数据集上的一次执行,有创建有撤销,存在是暂时的;
(2)程序是静态的观念,进程是动态的观念;
(3)进程具有并发性,而程序没有;
(4)进程是竞争计算机资源的基本单位,程序不是。
(5)进程和程序不是一一对应的:
一个程序可对应多个进程即多个进程可执行同一程序;
一个进程可以执行一个或几个程序
进程的内存布局
进程的内存布局分为四个不同的段
1.文本段——包含程序的源指令
2.数据段——包含了静态变量
3.堆——动态内存分区区域
4.栈——动态增长与收缩的段,保存本地变量
进程PCB
当进程执行时,它会被装载进虚拟内存,为程序变量分配空间,并把相关信息添加到task_struct里。
为了描述控制进程的运行,系统中存放进程的管理和控制信息的数据结构称为
进程控制块(PCB Process Control Block),它是进程实体的一部分,是操作系统中最重要的记录性数据结构。它是进程管理和控制的最重要的数据结构。
一般情况下,PCB中包含以下内容:
1.进程标识符(内部,外部)
2.处理机的信息(通用寄存器,指令计数器,PSW,用户的栈指针)。
说明进程当前所处的状态。为了管理的方便,系统设计时会将相同的状态的进程组成一个队列,如就绪进程队列,等待进程则要根据等待的事件组成多个等待队列,如等待打印机队列、等待等。
处理机状态信息主要是由处理机各种寄存器中的内容所组成。
通用寄存器。又称为用户可视寄存器,可被用户程 序访问,用于暂存信息。
指令寄存器。存放要访问的下一条指令的地址。
程序状态字PSW。其中含有状态信息。(条件码、 执行方式、中断屏蔽标志等)
用户栈指针。每个用户进程有一个或若干个与之相 关的系统栈,用于存放过程和系统调用参数及调用地址。栈指针指向该栈的栈顶。
3.进程调度信息(进程状态,进程的优先级,进程调度所需的其它信息,事件)
4.进程控制信息(程序的数据的地址,资源清单,进程同步和通信机制,链接指针)
Linux的进程控制块为一个由结构task _ struct所定义的数据结构,其中包括管理进程所需的各种信息。Linux系统的所有进程控制块组织成结构数组形式。
在创建一个新进程时,系统在内存中申请一个空的task_ struct区,即空闲PCB块,并填入所需信息。同时将指向该结构的指针填入到task[]数组中。当前处于运行状态进程的PCB用指针数组current_ set[]来指出。这是因为Linux支持多处理机系统,系统内可能存在多个同时运行的进程,故current_set定义成指针数组。
Linux系统的PCB包括很多参数,每个PCB约占1KB多的内存空间。用于表示PCB的结构task_struct简要描述如下:
struct task_struct{
...
unsigned short uid;
int pid;
int processor;
...
volatile long state;
long prority;
unsighed long rt_prority;
long counter;
unsigned long flags;
unsigned long policy;
...
Struct task_struct *next_task, *prev_task;
Struct task_struct *next_run,*prev_run;
Struct task_struct *p_opptr,*p_pptr,*p_cptr,*pysptr,*p_ptr;
...
};
下面对部分数据成员进行说明:
(1)unsigned short pid 为用户标识
(2)int pid 为进程标识
(3)int processor标识用户正在使用的CPU,以支持对称多处理机方式;
(4)volatile long state 标识进程的状态,可为下列六种状态之一:
可运行状态(TASK-RUNING);
可中断阻塞状态(TASK-UBERRUPTIBLE)
不可中断阻塞状态(TASK-UNINTERRUPTIBLE)
僵死状态(TASK-ZOMBLE)
暂停态(TASK_STOPPED)
交换态(TASK_SWAPPING)
(5)long prority**表示进程的优先级**
(6)unsigned long rt_prority 表示实时进程的优先级,对于普通进程无效
(7)long counter 为进程动态优先级计数器,用于进程轮转调度算法
(8)unsigned long policy 表示进程调度策略。
其值为下列三种情况之一:
SCHED_OTHER(值为0)对应普通进程优先级轮转法(round robin)
SCHED_FIFO(值为1)对应实时进程先来先服务算法;
SCHED_RR(值为2)对应实时进程优先级轮转法
(9)struct task_struct *next_task,*prev_task为进程PCB双向链表的前后项指针
(10)struct task_struct *next_run,*prev_run为就绪队列双向链表的前后项指针
(11)struct task_struct *p_opptr,*p_pptr,*p_cptr,*p_ysptr,*p_ptr指明进程家族间的关系,分别为指向祖父进程、父进程、子进程以及新老进程的指针。