目录
进程解释:
process in memory(进程在内存中包含什么) :
并发的进程:
进程定义:
个人定义:
书本定义:
进程状态:
进程何时离开CPU:
内部事件:
外部事件:
进程切换:
中断源:
特权指令和非特权指令:
模式切换:
进程切换:
进程控制块:
进程在物理内存中:
进程调度:
实验篇
进程解释:
process in memory(进程在内存中包含什么) :
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中的内存必须手动回收
并发的进程:
进程定义:
个人定义:
进程是一个拥有cpu使用权的进行计算任务的基本单位。
书本定义:
进程状态:
进程何时离开CPU:
内部事件:
外部事件:
new是一个新建状态,将程序加载入内存的状态当运行除了cpu之外的所有资源都就绪后进入就绪态当得到cpu权限后进入运行态,当运行完成后进入terminated状态(被动)在运行态cpu被抢夺后进入就绪态(主动)在运行态使用I/O设备的时候进入等待状态 等待结束重新进入就绪状态
进程切换:
中断源:
外中断:
来自处理器之外的硬件中断信号
如时钟中断、键盘中断、外围设备中断 外部中断均是异步中断
内中断(异常 Exception):
来自于处理器内部,指令执行过程中发生的中断,属同步中断
硬件异常:掉电、奇偶校验错误等
程序异常:非法操作、地址越界、断点、除数为0
系统调用
(参考书籍不同定义就不同---内中断应该只是说法不同 可能依次对应 终止、异常、陷入)
Exception(内)与interrupt(外)统称中断,发生中断后保存进程的上下文信息(相当于快照)(pc---在上边说到程序转换成了二进制指令,不止pc)执行中断处理程序(进入内核),选择对应进程进行恢复进程上下文,返回进程的执行。
特权指令和非特权指令:
通过硬件,设置一个比特位
模式切换:
进程切换:
3)修改被中断进程的控制信息(如状态等)
2、3两步会保存到该进程的PCB进程控制块,当重新得到cpu的控制权的时候会将PCB进程控制块加载到cpu
进程控制块:
每个进程都拥有一个自己的PCB进程控制块
进程在物理内存中:
进程调度:
实验篇:
Practice: How to create a child process?
这个实验在上一年学习Linux编程技术的的时候已经做过该实验,在这进行简单实验,若需要详细了解函数的原理可以查考Linux编程技术专栏。
补充:
调用fork()后,会把整个进程的信息进行copy完全复制给新创建的子进程,在fork()后
父子进程并发执行后边的程序,在子进程中fork函数的返回值为0,在父进程中会返回子进程的pid。(这里的并发可以根据打印信息的程序来判断--会无规律的进行交替打印)
getppid()函数是获得当前进程的父进程的pid(注:如果父进程在子进程结束之前结束,则子进程变成孤儿进程,则需要找1号进程(是系统启动的第一个进程INITD)作为父进程,即托管给系统进程)
为了避免孤儿进程的发生,我们引入了wait(NULL)方法,该方法作用与父进程,让父进程等待子进程结束后再返回。
代码如下: