目录
背景知识
冯诺依曼体系及操作系统
关于PCB(进程控制块)
进程的基本概念
进程状态
子进程
进程等待
进程地址空间
进程程序替换
背景知识
冯诺依曼体系及操作系统
关于PCB(进程控制块)
OS中可不可能存在大量的进程? 可能
那OS是不是需要将这些进程管理起来? 是的
如何管理? 先描述再组织
如何描述? OS在进程创建之时,为其创建PCB,这里记录的进程的所有属性信息。当然还会创建其他一些的数据结构,这里先不谈
而有了PCB,OS就能以统一的视角将进程管理起来,比如采用双向链表的方式(不一定就是这样,只是为了理解)
这样,所有的进程管理任务与进程对应的程序毫无关系而与PCB强相关
在PCB只是一个统称,类似于Xshell跟bash的关系
在Linux中,对应的PCB叫做task_struct?
从C语言的角度讲,这就是一个结构体,如果想了解PCB更多细节,自行查阅,这里只是给一个基本概念便于理解进程
进程的基本概念
什么是进程
进程:将程序加载到内存中,同时OS为其创建PCB等数据结构(维护),合称进程
ps:这是进程跟程序的区别!!程序只是存储在磁盘上的一个可执行文件!!
进程状态
所谓进程,在运行的时候,有可能因为运行的需要,会处于不同的队列之中
而在这不同的队列里,进程所处的状态是不一样的
R状态:处于运行队列,与CPU进行数据交互
S状态:处于等待队列,当进程需要完成某种任务,而任务条件不具备,需要进行某种等待
如利用输入函数等待用户写入数据时。(ps:这是浅度睡眠状态,可接受控制信号)
D状态:深度睡眠状态 不接受控制信号(了解即可)
T状态:暂停,完全停止。与S相比就是没有数据更新
t状态:调试的时候所处的状态
X状态:死亡状态,较不容易检测到,一旦进程处于X状态,OS会立即回收进程资源
(如进程相关的内核数据结构+自身代码和数据)
??
Z状态:僵尸状态:用于辨别死亡原因,如程序的退出信息。是否是正常退出等。
即进入X状态之前要先进入Z状态
子进程
如何创建子进程?
通过fork()函数? 创建成功返回子进程的pid(pid:进程的标识符,OS通过这个来识别是哪个进程)
子进程与父进程之间有什么关系?
子进程和父进程的代码是共享的,数据在默认情况下也是共享的
但是要考虑修改的情况
通过“写实拷贝”完成数据的独立性
子进程创建之后会执行fork之后的代码(原因是子进程是将OS给父进程的数据结构也拷贝了一份,pc指针(根据pc指针找到接下来要执行的代码)也拷贝了进来。
什么是孤儿进程?
当父进程退出而子进程还在运行
验证:子进程自动被1号进程领养?
进程等待
什么是进程等待?
通过fork()函数创建一个子进程帮助父进程完成某种任务,在fork()之后需要通过wait/waitpid
等待进程结束
为什么要进行进程等待?
1.保证时序问题,确保是子进程先于父进程退出,避免孤儿进程
2.通过获取子进程的退出信息,能够得知子进程的运行结果
3.退出时会先进入僵尸状态,会造成内存泄漏的问题,需要通过父进程wait释放该进程占用的资源
?具体的函数使用可以自行尝试
这里解释一下参数意思
wait是阻塞等待一个子进程结束(多个子进程则是最先结束那个)
status 表示子进程运行结果
是一个整形 只使用低16 如果是正常退出 则使用从右向左的前8位(记录退出码)
如果是异常退出 使用从左向右的前7位(记录退出信号)。第8位暂时不解释
waitpid 多了两个参数。 一个是要等待子进程的pid,而option是以什么方式等待
如果是第一个参数写入-1,而第3个参数写0(0默认阻塞等待)
则等价于wait ,等待一个最先结束的子进程?
如果第三个参数填入WNOHANG??
则为非阻塞等待(基于轮询)
非阻塞等待与阻塞等待的区别在于非阻塞等待可以在等待的同时干点其他事
而阻塞等待就是干等着。
说了这么多。阻塞的本质是什么呢?
进程的PCB被放入等待队列
同时进程状态改为S
返回的本质呢?
放入运行队列
同时进程状态改为R
进程地址空间
什么是进程地址空间?
OS在创建子进程的同时会为其创建一个数据结构(linux下为struct mm_struct)
这个就是进程地址空间 也叫虚拟内存。通过页表+MMU与真实物理内存建立映射关系
PCB中存在该结构体的指针,OS就是通过PCB中的这个指针找到对应的进程地址空间
为什么要有进程地址空间?
1.通过添加一层软件层,有效的完成对进程操作内存进行风险管理(权限管理)
本质目的是为了,保护物理内存及各个数据的内存安全
2.将内存申请和内存使用的概念在时间分清楚,通过虚拟底层空间屏蔽底层申请内存的过程
达到进程读写内存和OS进行内存管理操作,进行软件上面分离
3.站在CPU和应用层的角度,进程统一可以看做统一使用相同的内存空间,而且每个空间的相对位置是比较确定的
OS这样设计的目的?
每个进程都认为自己独占系统资源-->进程具有独立性
进程程序替换
什么是程序替换?
进程在运行过中,在创建子进程之后,可以不让子进程执行跟父进程相同的代码
而是通过程序替换的方式,执行一个全新的程序
怎么进行程序替换?
通过下面几个函数
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ...,char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
这几个是C语言层面的函数
本质上都是调用下面这个系统调用函数
?这里解释一下execl?
第一个参数,表示指明替换程序所在路径,后面的可变参数列表表示你想怎么执行
看图
?执行结果
?而execv表示以数组的形式说明你要怎么执行,execl就是以链式的方式
带p是表示有从环境变量从找文件所在的路径
|