目录
进程解释:
process in memory(进程在内存中包含什么) :
并发的进程:
进程定义:
个人定义:
书本定义:
进程状态:
进程何时离开CPU:
内部事件:
外部事件:
进程切换:
中断源:
特权指令和非特权指令:
模式切换:
进程切换:
进程控制块:
进程在物理内存中:
进程调度:
实验篇
进程解释:
1)A
program(程序)
is a
passive entity(被动的实体)
, such as a file
containing a list of instructions stored on disk(often
called an
executable file--可执行文件
).---例如一个文件包含一列指令存储在磁盘
2)A
program
becomes a
process
when an executable file
is loaded into memory.(当可执行文件(指令)被加载进内存的时候一个程序就变成了进程)
3)A
process
is an
active entity
, with a
program counter(pc)
specifying the next instruction to execute an a set of
associated resources.(一个进程是一个活动实体,包含一个程序计数器,规定用来指明下一条要执行的指令---pc+1加的是一个字长)
process in memory(进程在内存中包含什么) :
text:二进制代码(指令)(同一个应用程序的不同进程之间是共享程序段的)
data:全局和静态变量数据
stack:栈用于存放局部变量、函数返回地址
heap:堆用于程序
运行时
的动态内存分配
还包括pcb进程控制块
int global=100;
void f(int x, int y){
int* p = malloc(100);
return;
}
void g(int a){
f(a, a+1);
return;
}
int main()
{
static int i=10;
g(i);
return 0;
}
将程序加载入内存
代码的二进制指令全部放入text区--------存放的指令是只读的
先执行main函数指令 将main函数的返回地址写入栈(stack)中
发现一个全局变量和一个静态变量放入data区(编译好的代码是有全局观的,所以会知道有全局变量)
调用函数g(), 把g()函数的局部变量放入栈中,并把函数的返回值压入栈中,
调用f()函数,把f函数的局部变量x,y,p放入栈中,再将f()函数的返回值放入
f()函数申请的动态内存放入heap,申请的空间内存的首地址赋值给p指针
从stack栈中得到f()函数的返回地址,让后出栈,同时函数清理需要把该函数的所有变量从栈中清掉。
取出g()函数返回地址,清空g()函数
取出main()函数的返回值,并清空栈中与data区中的数据
heap中的内存必须手动回收
并发的进程:
Concurrency:the fact of two or more events or
circumstances happening or existing at the same time.
(并发:两个或多个事件的事实同时
发生或存在的情况---不是同时runing运行--并行)
进程定义:
个人定义:
进程是一个拥有cpu使用权的进行计算任务的基本单位。
书本定义:
进程是一个程序的一次执行过程
能完成具体的功能
是在某个数据集合上完成的
执行过程是可并发的
进程是资源分配、保护和调度的基本单位
进程状态:
进程在执行期间自身的状态会发生变化,进程有三 种基本状态,分别是:
运行态(Running)
:此时进程的代码在CPU上运行(正在执行的才是运行态)
就绪态(Ready)
:进程具备运行条件,等待分配CPU
等待态(Waiting)
:进程在等待某些事件的发生(比如 IO操作结束或是一个信号)(不具备运行条件)
进程何时离开CPU:
内部事件:
进程
主动放弃(yield)
CPU,进入等待/终止状态。
E.g 使用I/O设备(等待),(非)正常结束(终止)。
外部事件:
进程被剥夺CPU使用权,进入就绪状态。这个动作叫
抢占(preempt)
。
E.g 时间片到达,高优先权进程到达。
new是一个新建状态,将程序加载入内存的状态
当运行除了cpu之外的所有资源都就绪后进入就绪态
当得到cpu权限后进入运行态,当运行完成后进入terminated状态
(被动)在运行态cpu被抢夺后进入就绪态
(主动)在运行态使用I/O设备的时候进入等待状态 等待结束重新进入就绪状态
进程切换:
并发进程中,一个进程在执行过程中可能会被另一个进程替换占有CPU,这个过程称作“进程切换”
中断源:
外中断:
来自处理器之外的硬件中断信号
如时钟中断、键盘中断、外围设备中断 外部中断均是异步中断
内中断(异常 Exception):
来自于处理器内部,指令执行过程中发生的中断,属同步中断
硬件异常:掉电、奇偶校验错误等
程序异常:非法操作、地址越界、断点、除数为0
系统调用
(参考书籍不同定义就不同---内中断应该只是说法不同 可能依次对应 终止、异常、陷入)
Exception(内)与interrupt(外)统称中断,发生中断后保存进程的上下文信息(相当于快照)(pc---在上边说到程序转换成了二进制指令,不止pc)执行中断处理程序(进入内核),选择对应进程进行恢复进程上下文,返回进程的执行。
特权指令和非特权指令:
Privileged Instructions
The Instructions that can run
only
in
Kernel Mode
are called Privileged Instructions .
*I/O instructions and Halt instructions(I/O指令/停止指令)
*Turn off all Interrupts(关闭中断)
*Set the Timer (设置时钟定时器)
*Process Switching (进程切换)
Non-Privileged Instructions
*The Instructions that can run
only
in
User Mode
are called Non-Privileged Instructions .
怎么区分特权指令和非特权指令?
通过硬件,设置一个比特位
模式切换:
*中断是用户态向核心态转换的唯一途径!系统调用 实质上也是一种中断。
*OS提供Load PSW指令装载用户进程返回用户状态
进程切换:
1)在进程切换的第一步将cpu的user mode 切换到核心 mode
2)保存被中断进程的上下文信息
3)修改被中断进程的控制信息(如状态等)
2、3两步会保存到该进程的PCB进程控制块,当重新得到cpu的控制权的时候会将PCB进程控制块加载到cpu
4)将被中断的进程加入相应的
状态队列
5)调度
一个新的进程并恢复它的上下文信息
进程控制块:
每个进程都拥有一个自己的PCB进程控制块
A Process
Control
Block(PCB)contains many pieces of information associated with a specific
process.(一个进程控制块包含很多信息,与一个特定的进程有关)
进程在物理内存中:
进程的进程实体并不是整体存放,而是离散存放
管理进程使用的是进程队列进行管理:
只有俩个状态--ready(就绪)/等待状态,运行态没用队列只有一个
就绪状态队列是使用链表进行连接形成队列(只是连接的pcb),当某个队列需要进入runing状态则从就绪队列中移除
进程调度:
进程在整个生命周期中会在各个调度队列中迁移, 由操作系统的一个调度器(scheduler)来执行
这里的主动与被动是相对于自身发生的事件来观察的
eg:当I/O请求发生后cpu是主动离开
当时间片结束是操作系统剥夺cpu的执行权,被动
创建子进程,调用wait函数进行等待,当子进程结束后主动离开
等待中断,当中断发生后立即交出cpu的执行权。
实验篇:
Practice: How to create a child process?
这个实验在上一年学习Linux编程技术的的时候已经做过该实验,在这进行简单实验,若需要详细了解函数的原理可以查考Linux编程技术专栏。
补充:
调用fork()后,会把整个进程的信息进行copy完全复制给新创建的子进程,且两者的内存空间是相互独立的,在fork()后父子进程并发执行后边的程序,在子进程中fork函数的返回值为0,在父进程中会返回子进程的pid。(这里的并发可以根据打印信息的程序来判断--会无规律的进行交替打印)
getppid()函数是获得当前进程的父进程的pid(注:如果父进程在子进程结束之前结束,则子进程变成孤儿进程,则需要找1号进程(是系统启动的第一个进程INITD)作为父进程,即托管给系统进程)
为了避免孤儿进程的发生,我们引入了wait(NULL)方法,该方法作用与父进程,让父进程等待子进程结束后再返回。
代码如下: