一、进程原理
1、什么是进程?
进程就是执行中的程序。
- 从物理内存的分配来看,每个进程占用一片内存空间,即进程就是内存的某片空间,由于CPU只能执行一条指令,所以执行指令的顺序由程序计数器决定。
- 从逻辑上看,每个程序可以执行也可以暂时挂起让别的程序执行,之后又可以接着继续执行。所以每个进程都有一个计数器,记录下一条指令的位置,从而使继续接着运行时能找到正确地址。
- 从时间上看,在运行一定时间后,进程都已经完成了一定的工作量,即,每个进程都必须向前推进。
2、进程的产生与消失
(1)对于进程,所做的就是:
- 系统初始化
- 执行进程创建程序
(2)用户请求创建新进程
在系统进行初始化时,将有许多进程产生。
在系统初始化时,系统就等待用户输入命令。如果此用户启动一个程序,比如双击一个可执行文件,那么系统将会为这个可执行文件创立一个进程。除此之外,用户也可在程序中通过系统调用(fork)直接生成新进程。
(3)造成进程消亡的原因: - 寿终:进程云心完成而退出(自愿)
- 自杀:进程因错误而自行退出(自愿)
- 他杀:进程被其他进程强行杀死(非自愿)
通常是一个父进程杀死一个子进程。用户也可以杀死自己的进程。 - 处决:进程因异常而强行终结(非自愿)
3、进程状态
- 就绪态:等待CPU调度执行
- 执行态:CPU正在执行的进程指令
- 阻塞态:等待事件发生
- 执行态——>就绪态:系统给每个进程分配一个时间片,当时间片用完,无论是何种状态,就将其转入就绪,在执行另一个进程
- 当阻塞挂起的过程中事件发生了,就会把阻塞挂起的进程放在就绪挂起中。
4、进程与地址空间
进程空间也称地址空间,地址空间就是进程要用的所有资源。进程与地址空间研究的是如何让多个进程空间共享一个物理内存。
二、写时拷贝技术
1、进程的创建方法
2、前言
- 一个现有的进程可以调用fork函数创建一个新进程。
- 由于fork创建的新进程被称为子进程。fork函数被调用一次,但返回两次,子进程返回值为0,父进程的返回值则是新的子进程的进程ID。
- 子进程返回0 的原因:
一个进程只会有唯一的一个父进程,所以子进程总是可以调用getppid来获取父进程的进程ID。 - 父进程返回子进程ID的原因:
一个进程的子进程可以有很多个,没办法获取其所有子进程的进程ID。 - 子进程和父进程继续执行fork之后的指令,子进程相当于是父进程的副本。父子进程并不共享存储空间。
3、写时拷贝技术
(1)传统的fork()系统调用直接把所有资源复制给新创建的进程。由于在fork之后经常会跟随着exec(进程替换的方法),所以现在很多实现并不执行一个父进程数据段、栈和堆的完全复制。也就是作为替代使用了写时拷贝技术。
(2)这些区域由父子进程共享,而且内核将他们的访问权限改为只读。如果父子进程中的任意一个试图修改这些区域,则内核只为修改区域的那块内存创建一个副本。
(3)使用写时拷贝技术时,内核并不会复制整个进程地址空间,而是让父子进程共享同一个拷贝。只有在需要写入的时候数据才会被复制,从而使各个进程拥有自己的拷贝。也就是说,资源的复制只有在需要写入的时候才进行,除此之外,只是以只读形式进行共享。