基本概念
- 课本概念:程序的一次执行实例,正在执行的程序等。
- 内核观点:担当分配系统资源(CPU时间,内存)的实体。
- 每个进程都有自己是状态
每个进程都有自己的虚拟地址空间
进程是操作系统分配资源的基本单位
描述进程PCB
PCB(结构体)—-进程控制块: 操作系统管理控制进程运行所用的信息集合。
- 操作系统用PCB来描述进程的基本情况以及运行变化的进程
- PCB是进程存在的唯一标志,即每个进程都在操作系统中有一个对应的PCB
- 包含信息:PID进程标识符、进程间通信、信号( 结束)
进程的生命周期划分:
进程创建、进程执行、进程等待、进程抢占、进程唤醒、进程结束
引起进程创建的情况:
- 系统初始化时
- 用户请求创建一个新进程
- 正在运行的进程执行了创建进程的系统调用
进程执行:
内核选择一个就绪的进程,让他占用处理机并执行。
那么不止一个进程,如何进行选择?——处理机的调度算法进程进入等待(阻塞)状态的情况:
- 请求并等待系统服务,无法马上完成
- 启动某种操作,无法马上完成
- 需要的数据没有到达
- 只有进程自身才能知道何时需要等待某种事件的发生(进程本身内部原因造成)
进程被抢占的情况:
- 高优先级进程就绪
- 进程执行当前时间用完
唤醒进程的情况:
- 被阻塞进程需要的资源可被满足
- 被阻塞进程等待的事件到达
- 进程只能被别的进程或操作系统唤醒(不会因为自身原因回去)
进程结束(消亡)的情况:
- 正常退出(自愿的)
- 错误退出(自愿的)
- 致命错误(强制性的)
- 被其他进程所杀(强制性的)
调度算法
进程调度:在操作系统中调度是指一种资源分配。
调度算法是指: 根据系统的资源分配策略所规定的资源分配算法。
操作系统管理了系统的有限资源,当有多个进程(或多个进程发出的请求)要使用这些资源时,因为资源的有限性,必须按照一定的原则选择进程(请求)来占用资源。这就是调度。目的是控制资源使用者的数量,选取资源使用者许可占用资源或占用资源。
1. 先来先服务:
- 概念:
如果早就绪的进程排在就绪队列的前面,迟就绪的进程排在就绪队列的后面,那么先来先服务(FCFS: first come first service)总是把当前处于就绪队列之首的那个进程调度到运行状态。也就说,它只考虑进程进入就绪队列的先后,而不考虑它的下一个CPU周期的长短及其他因素。
- 要领:
按照进程进入就绪队列的先后顺序调度并分配处理机执行。先来先服务调度算法是一种非抢占式的算法,先进入就绪队列的进程,先分配处理机运行。一旦一个进程占有了处理机,它就一直运行下去,直到该进程完成工作或者因为等待某事件发生而不能继续运行时才释放处理机。
(1)系统只要有按FIFO规则建立的后备作业队列或就绪进程队列即可,就是一个作业控制块JCB或进程控制块PCB加入队列时加在相应队列末尾。
(2)调度退出队列时从相应队列首开始顺序扫描,将相关的JCB或PCB调度移出相应
- 优缺点
优点:有利于长作业以及CPU繁忙的作业
缺点:不利于短作业以及I/O繁忙的作业队列。
2. 短作业(进程)优先调度算法SJ(P)F
- 概念:
对预计执行时间短的作业(进程)优先分派处理机.通常后来的短作业不抢先正在执行的作业.
- 优缺点
(1)优点:
比FCFS改善平均周转时间和平均带权周转时间,缩短作业的等待时间;
提高系统的吞吐量;
(2)缺点:
对长作业非常不利,可能长时间得不到执行;
未能依据作业的紧迫程度来划分执行的优先级;
难以准确估计作业(进程)的执行时间,从而影响调度性能。
3. 轮转法
- 概念:
让每个进程在就绪队列中的等待时间与享受服务的时间成正比例。
- 定义:
时间片轮转法类似于“轮流坐庄”的思想,条件是:各作业近似认为“同时”到达,题中条件是后面作业依次比前一个作业迟到一个时间单位,分析时要严格按照RR调度算法的实现思想:系统把所有就绪进程按先入先出的原则排成一个队列。新来的进程加到就绪队列末尾。每当执行进程调度时,进程调度程序总是选出就绪队列的对首进程,让它在CPU上运行一个时间片的时间。当进程用完分给它的时间片后,调度程序便停止该进程的运行,并把它放入就绪队列的末尾。
4. 多级反馈队列算法
- 概念:
设置多个就绪队列,分别赋予不同的优先级,如逐级降低,队列1的优先级最高。每个队列执行时间片的长度也不同,规定优先级越低则时间片越长,如逐级加倍。
新进程进入内存后,先投入队列1的末尾,按FCFS算法调度;若按队列1一个时间片未能执行完,则降低投入到队列2的末尾,同样按FCFS算法调度;如此下去,降低到最后的队列,则按“时间片轮转”算法调度直到完成。
仅当较高优先级的队列为空,才调度较低优先级的队列中的进程执行。如果进程执行时有新进程进入较高优先级的队列,则抢先执行新进程,并把被抢先的进程投入原队列的末尾。
多级反馈队列调度算法又称反馈循环队列或多队列策略,主要思想是将就绪进程分为两级或多级,系统相应建立两个或多个就绪进程队列,较高优先级的队列一般分配给较短的时间片。处理器调度先从高级就绪进程队列中选取可占有处理器的进程,只有在选不到时,才从较低级的就绪进程队列中选取。
- 优点:
为提高系统吞吐量和缩短平均周转时间而照顾短进程。
为获得较好的I/O设备利用率和缩短响应时间而照顾I/O型进程。
不必估计进程的执行时间,动态调节
进程状态修改
- fork之后父子进程胶原体运行
- kill 杀死
子进程死亡后,称为僵尸进程
执行结果
父进程死亡后,子进程变成孤儿进程,由1号进程领养
执行结果
ps 查看进程状态
- PRI(new)=PRI(old)+nice
- 当nice为负值的时候,那么该程序的优先级值将变小,即其优先级会变高,则其越快被执行
- nice取值范围在-20~19,一共40个级别
- 进程的nice值不是进程的优先级,但是进程nice值会影响到进程的优先级变化,可以理解nice值是进程优先级的修正数据
进程是不可能并行运行的(即使多CPU),只能并发运行
线程可以在多CPU或多核并行运行
多核和多CPU不一样
环境变量
基本概念
一般是指在操作系统中用来指定操作系统运行环境的的参数
本地变量:只能在当前进程使用
环境变量:在当前进程及其子进程中使用查看环境变量
export name=val(注意:=左右不能有空格)
env 获取全部环境变量
echo $NAME 打印出对应的环境变量值
在程序中获取环境变量:
获取所有的环境变量:main的第三个参数envp
获取某一个环境变量:val=getenv(“name”);
在程序中设置环境变量:putenv(“name=value”);
错误处理
LINUX绝大部分函数出错返回值都是-1
int errno
LINUX函数出错以后,将错误编号放在errno全局变量中
if(fork()==-1)
errno;
char *strerror(errno)
通过错误编号,返回错误信息
#include <errnno.h>
#include <string.h>
printf("fork:%s",strerror(errno));
perror(cmd=:fork")
{
printf("%s:%s\n",cmd,strerror(errno));
}