计算机考研——操作系统【进程管理】

进程与线程

【考点笔记1】进程与线程的比较

进程线程
映像组成由程序段、相关数据段和PCB组成共享其隶属进程的进程映像,仅拥有线程ID、寄存器集合和堆栈等
并发性没有引入线程的系统中,进程是独立运行的基本单位线程是独立运行的基本单位,一个进程可以拥有一个或多个线程
资源分配进程是资源分配和拥有的基本单位线程自己基本不拥有系统资源,但它可以访问所属进程所拥有的的全部资源
调度在没有引入线程的操作系统中,进程是独立调度和分派的基本单位引入线程后的操作系统中,线程是独立调度和分派的基本单位
通信PV操作;共享存储;
消息传递;管道通信
同一进程的各线程直接读写进程数据段。
不同进程的线程之间通信属于进程间通信。
系统开销进程切换时涉及当前CPU环境的保存以及新进程CPU环境的设置,系统开销大线程切换时只需保存和设置少量寄存器内容,开销很小
地址空间进程的地址空间之间互相独立同一进程的各线程间共享进程的地址空间

进程状态与进程控制

【考点笔记2】进程状态转换
在这里插入图片描述
【考点笔记3】进程的阻塞与唤醒

进程阻塞进程唤醒
引发事件请求系统服务。
启动某种操作。
新数据尚未到达
无新工作可做
引发阻塞的事件完成
特点阻塞:运行状态->阻塞状态
进程通过调用阻塞原语block把自己阻塞。进程的阻塞是进程自身的一种主动行为。
唤醒:阻塞状态->就绪状态
由相关事件的进程调用weakup原语将阻塞进程唤醒,是被动完成的。

进程阻塞的引发事件可总结为:需要等待某个事件的发生时引发阻塞
进程唤醒的引发事件可总结为:等待的事件发生时唤醒进程

处理机调度

【考点笔记4】调度的原则

指标定义原则
CPU利用率CPU的工作时间在整个系统工作时间中所占的比例
系统吞吐量系统吞吐量表示单位时间内CPU完成作业的数量
周转时间周转时间=作业完成时间-作业提交时间
平均周转时间平均周转时间=(作业1周转时间+···+作业n周转时间)/n
带权周转时间带权周转时间=作业周转时间/作业实际运行时间
平均带权周转时间平均带权周转时间=(作业1的带权周转时间+···)/n
等待时间进程处于等待处理机状态的时间之和
响应时间从用户提交请求到系统首次产生响应所用的时间

【考点笔记5】调度的基本概念
调度从作业提交到完成可以分为:作业调度、中级调度、进程调度三个层次:
在这里插入图片描述【考点笔记6】进程调度的优先级
根据进程创建后其优先级是否可以改变,可以将进程优先级分为以下两种:
1)静态优先级。在进程投入运行前就确定了一个优先级,并且之后一直不变。
2)动态优先级。在进程运行过程中,根据进程情况的变化动态的调整优先级。

通常(静态优先级):
系统进程优先级 高于 用户进程;
前台进程优先级 高于 后台进程;
I/O型进程(或称I/O繁忙型进程)优先级 高于 计算型进程(CPU繁忙行进程)

【考点笔记7】典型的调度算法

算法
调度方法
特点
先来先服务调度算法    作业:每次从后背作业队列中选择最先进入该队列的作业调入内存。
    进程:每次从就绪队列中选择最先进入该队列的进程,将处理器分配给它,使之投入运行。
1.算法简单,但效率低;
2.有利于长作业,不利于短作业;
3.有利于CPU繁忙型作业而不利于I/O繁忙型作业。
短作业/进程优先调度算法    作业:每次从后背队列中选择一个或若干个估计运行时间最短的作业,将它们调入内存。
    进程:每次从就绪队列中选择一个估计运行时间最短的进程,将处理器分配给它,使之投入运行。
1.对长作业不利;
2.估计运行时间可能不准确;
3.平均等待时间、平均周转时间最少
高响应比优先调度算法    先计算后备队列中每个作业的响应比,从中选出响应比最高的作业投入内存。
响 应 比 R P = 等 待 时 间 + 要 求 服 务 时 间 要 求 服 务 时 间 响应比R_P=\frac{等待时间+要求服务时间}{要求服务时间} RP=+
    综合考虑了作业的等待时间和估计运行时间
1.有利于短作业;
2.长作业不至于产生饥饿;
3.等待时间越长,优先级越高
优先级调度算法    作业:每次从后备队列中选择优先级最高的一个或几个作业,将它们调入内存。
    进程:每次从就绪队列中选择优先级最高的进程,将处理器分配给它,使之投入运行。
    优先级高的先运行。优先级分为静态优先级:创建时确定且不变。动态优先级:创建时确定并动态改变。
时间片轮转调度算法    所有就绪进程按照先来先服务排队,总是选择就绪队列中第一个进程运行一个时间片。然后释放处理器给下一个就绪进程,而被剥夺处理器的进程返回到就绪队列的末尾重新排队。    所有用户在给定时间内得到响应。时间片大:系统开销小但交互性差。时间片小:有利于短作业,但系统开销大。
多级反馈队列调度算法(适用于分时系统进程调度)    1.设置多个就绪队列,优先级越高的队列进程的运行时间片就越小。优先级按第1~n级队列递减。
    2.当一个新进程进入内存后,首先将它放入第1级队列的末尾,按FCFS原则排队等待调度。
    当轮到位于第i级队列的某一进程执行时,若它在该时间片内完成,便可撤离系统,否则
     **第1~(n-1)级队列:将该进程转入下一级队列的末尾,等待下次调度运行。
    **第n级队列:采用时间片轮转的方式运行。
    3.仅当第1~(i-1)级队列均为空时,才会调度第i级队列中的进程运行。
    4.第i级队列中的进程运行时,若又有新进程进入第1~(i-1)中的任一队列,则把正在运行的进程放回第i级队列的末尾,把处理器分配给新进程。
1.终端型作业用户:短作业优先
2.短批处理作业用户:周转时间较短
3.长批处理作业用户:不会长期得不到处理

进程同步与互斥

为了实现对临界资源的互斥访问,同时保证系统整体性能,需要遵循以下原则:

原则
含义
空闲让进临界区空闲时,可以允许一个请求进入临界区的进程立即进入临界区
忙则等待当已有进程进入临界区时,其他试图进入临界区的进程必须等待
有限等待对请求访问的进程,应保证能在有限时间内进入临界区(保证不会饥饿)
让权等待当进程不能进入临界区时,应立即释放处理机,防止进程忙等

互斥的四种实现方式——单标志法、双标志先检查法、双标志后检查法、Peterson算法。

【考点笔记8】临界区互斥的软件实现方法
对两个进程P0、P1互斥访问临界区的软件实现方法:
单标志法

特点:

  • 确保两个进程互斥访问临界区。
  • 两个进程必须交替进入临界区。
  • 违反“空闲让进”原则

设置一个公共整型变量turn,用于指示被允许进入临界区的进程编号,即若turn==0,则允许P0进程进入临界区

P0进程:
while(turn!=0);    //进入区--检查自己是否拥有访问临界区的权限
critical section;  //临界区--将临界区的访问权让给另一个进程
turn = 1;          //退出区
remainder section; //剩余区

P1进程:
while(turn!=1);    //进入区--检查自己是否拥有访问临界区的权限
critical section;  //临界区--将临界区的访问权让给另一个进程
turn = 0;          //退出区
remainder section; //剩余区

双标志先检查法

特点:

  • 进程不必交替进入,可连续使用
  • 两进程可能同时进入临界区,无法实现互斥访问,违背“忙则等待”

设置了一个数组flag[2],表示进程是否进入临界区。若flag[i]值为FALSE,表示Pi进程未进入临界区;值为TRUE,表示Pi进程进入临界区(i=0或1)。

补充说明:flag[i]表示Pi进程想要进入临界区的意愿。初始时flag[0]=flase,flag[1]=false

P0进程:
while(flag[1]);      //进入区--检查对方是否想进入临界区,如果对方想进入,自己就循环等待
flag[0]=TRUE;        //进入区--上锁
critical section;    //临界区
flag[0]=FALSE;       //退出区
remainder section;   //剩余区

P1进程:
while(flag[0]);      //进入区--检查对方是否想进入临界区,如果对方想进入,自己就循环等待
flag[0]=TRUE;        //进入区--上锁
critical section;    //临界区
flag[0]=FALSE;       //退出区
remainder section;   //剩余区

双标志后检查法

特点:

  • 确保进程互斥访问临界区
  • 存在两个进程都进不了临界区的“饥饿”现象,违背“空闲让进”、“有限等待”

设置flag[2],采用先设置自己标志后,再检测对应状态标志,若对方标志位为TRUE,则进程等待;否则进入临界区。

P0进程:
flag[0]=TRUE;       //进入区--上锁
while(flag[1]);     //进入区--检查
critical section;   //临界区
flag[0]=FALSE;      //退出区
remainder section;  //剩余区

P1进程:
flag[1]=TRUE;       //进入区--上锁
while(flag[0]);     //进入区--检查
critical section;   //临界区
flag[1]=FALSE;      //退出区
remainder section;  //剩余区

皮特森算法

特点:

  • 确保进程互斥访问临界区
  • 不会出现“饥饿”现象
  • 不满足“让权等待”原则,暂时不能进入临界区的进程还会占用处理机
    (在while循环处一直轮询,看是否可以进入临界区)

设置变量turn(表示一种“谦让”,优先让哪个进程进入临界区)以指示不允许进入临界区的进程编号,每个进程在先设置自己的flag标志后再设置turn标志,不允许另一个进程进入。这时,再同时检测另一个进程flag标志和不允许进入标志turn。若对方flag标志位为TRUE且turn显示不允许对方进入临界区,则进程进入临界区;否则等待。

P0进程:
flag[0]=TRUE;     //进入区--表明自己想进入临界区的意愿
turn =1;          //进入区--表示可以优先让对方进入
while(flag[1]&&turn==1);//进入区--若对方也想进入,且最后使自己做出了“谦让动作”,则自己等待
critical section;
flag[0]=FALSE;
remainder section;

P0进程:
flag[0]=TRUE;     //进入区--表明自己想进入临界区的意愿
turn =1;          //进入区--表示可以优先让对方进入
while(flag[1]&&turn==1);//进入区--若对方也想进入,且最后使自己做出了“谦让动作”,则自己等待
critical section;
flag[0]=FALSE;
remainder section;

【考点笔记9】信号量机制

整型信号量: 一个用于表示资源个数的整型量S。当进程发现S<=0时,就会不断测试。因此进程处于忙等状态,未遵循“让权等待”原则。

记录型信号量 :遵循了让权“让权等待”原则,其数据结构描述如下。
typedef struct{
    int value; //代表资源数目
    struct process *L; //链接等待资源的进程
}semaphore;
信号量的P、V操作的实质是“加减”操作,P、V操作又是原语操作,所以,P操作是对信号量(只能对信号量,不能对普通变量)进行减“1”操作,然后判断是否小于零,“是”则阻塞等待,“否”则什么都不做。而V操作是对信号量加“1”操作,然后判断是否小于等于零,“是”则唤醒进程,“否”则什么也不做。

记录型信号量S中value值的意义:

  • S.value的初值表示系统中某类资源的总数
  • S.value<0表示当前系统中已经没有可用的该类资源
  • S.value<0时,其绝对值表示等待该资源而阻塞的进程的个数

生产者-消费者问题
生产者、消费者共享一个初始为空、大小为n的缓冲区。
只有缓冲区没满时,生产者才能把产品放入缓冲区,否则必须等待。
只有缓冲区不空时,消费者才能从中取出产品,否则必须等待。
缓冲区是临街资源,各进程必须互斥地访问。

semaphore mutex = 1;//互斥信号量,实现对缓冲区的互斥访问
semaphore empty = n;//同步信号量,表示空闲缓冲区的数量
semaphore full = 0; //同步信号量,表示产品的数量,也即非空缓冲区的数量
producer(){
    while(1){
        生产一个产品;
        P(empty);  //消耗一个空缓冲区
        P(mutex);
        把产品放入缓冲区;
        V(mutex);
        V(full);  //增加一个产品
    }
}
consumer(){
    while(1){
        P(full);  //消耗一个产品(非空缓冲区)
        P(mutex);
        从缓冲区中取出一个产品;
        V(mutex);
        V(empty);  //增加一个空闲缓冲区
    }
}

注: 实现互斥的P操作一定要在实现同步的P操作之后,否则可能会发生死锁。

读者-写者问题
有读者和写者两组并发进程,共享一个文件,当两个或两个以上的读进程同时访问共享数据时不会产生副作用,但若某个写进程和其他进程(读进程或写进程)同时访问共享数据时,则可能导致数据不一致的错误。因此要求:
1.允许多个读者可以同时对文件执行读操作
2.只允许一个写者往文件中写信息
3.任一写者在完成写操作之前不允许其他读者或写者工作
4.写者执行写操作前,应让已有的读者和写者完全退出

semaphore rw=1;//用于实现对文件的互斥访问,表示当前是否有进程在访问共享文件
int count=0;//记录当前有几个人读进程在访问文件
semaphore mutex=1;//用于保证对count变量的互斥访问

writer(){
    while(1){
        P(rw);   //写之前“加锁”
        写文件...
        V(rw);   //写之前“解锁”
    }
}

reader(){
    while(1){
        P(mutext);   //各读进程互斥访问count
        if(count==0)
            P(rw);   //第一个读进程负责“加锁”
        count++;     //访问文件的读进程数+1
        V(mutex);
        读文件...
        P(mutex);   //各读进程互斥访问count
        count--;     //访问文件的读进程数-1
        if(count==0)
            V(rw);   //最后一个读进程负责“解锁”
        V(mutex);
    }
}

**潜在的问题:只要有读进程还在读,写进程就要一直阻塞等待,可能“饿死”,因此,这种算法中,读进程是优先的。

实现相对公平的 读者-写者问题
写者不会饥饿,是相对公平的 先来先服务 原则。也叫“读写公平法”

//互斥信号量初值为1
semaphore rw=1;//用于实现对文件的互斥访问
int count = 0;//记录当前有几个读进程在访问文件
semaphore mutex=1;//用于保证对count变量的互斥访问
semaphore w = 1;//用于实现“写优先”
writer(){
    while(1){
        P(w);
        P(rw);
        写文件...
        V(rw);
        V(w);
    }
}

reader(){
    while(1){
        P(w);
        P(mutex);
        if(count==0)
            P(rw);
        count++;
        V(mutex);
        V(w);
        读文件...
        P(mutex);
        count--;
        if(count==0)
            V(rw);
        V(mutex);
    }
}

读者-写者问题总结:
    其核心思想在于设置了一个计数器count,用来记录当前正在访问的共享文件的读进程数。我们可以用count的值来判断当前进入的进程是否是第一个/最后一个读进程,从而做出不同的处理。
    另外,对于count变量的检查和复制不能一气呵成导致了一些错误,如果需要实现“一气呵成”,自然应该想到用互斥信号量。
    最后,还要认真体会我们是如何解决“写进程饥饿”问题的

哲学家进餐问题
一张圆桌上坐着5名哲学家,每两个哲学家之间的桌上摆了一根筷子,桌子的中间是一碗米饭。哲学家们倾注毕生的精力用于思考和进餐,哲学家在思考时,并不影响他人。只有当哲学家饥饿时,才试图拿起左、右两根筷子(一根一根地拿起)。如果筷子已在他人手上,则需等待。饥饿的哲学家只有同时拿起两根筷子才可以开始进餐,当进餐完毕后,放下筷子继续思考。

semaphore chopstick[5]={1,1,1,1,1};
semaphore mutex = 1;
Pi(){
    while(1){
        P(mutex);
        P(chopstick[i]);
        P(chopstick[(i+1)%5];
        V(mutex);
        吃饭...
        V(chopstick[i]);
        V(chopstick[(i+1)%5];
        思考...
    }
}

1.mutex保证了同一时刻最多只有一个哲学家正在“拿筷子”。也就是说,最多只有一个哲学家处于“请求和保持”的状态(占有了一支筷子的同时申请另一支筷子)。别的哲学家要么手里没有筷子,要么有两支筷子。手里有两只筷子的哲学家一定可以顺利运行结束,并释放筷子,唤醒处于“请求和保持”状态的哲学家。
2.哲学家进餐问题的关键在于解决进程死锁。
这些进程知己恩只存在互斥关系,但与之前的互斥关系不同的是,每个进程都需要同时持有两个临界资源,因此就有“死锁”问题的隐患。

解决哲学家进餐问题死锁的方案:(方法2为代码所描述的方法)
1.最多只允许四个哲学家同时进餐
2.仅当一个哲学家左右两边的筷子同时可用时,他才可以拿起筷子
3.将哲学家编号,要求奇数号的哲学家先拿左边筷子,偶数号哲学家先拿右边筷子

死锁

【考点笔记10】死锁条件
产生死锁必须同时满足一下四个条件,只要其中任一个条件不成立,死锁就不会发生。

条件解释
互斥条件在一段时间内某资源仅为一个进程所占有。此时若有其他进程请求资源,则请求进程只能等待
不剥夺条件进程获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的进程自己来释放
请求和保持条件进程已经保持了至少一种资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程被阻塞,但对自己获得的资源保持不放
循环等待条件存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被链中下一个进程所请求

1.预防死锁:破坏思索的四个必要条件中的一个或几个
2.避免死锁:用某种方式防止系统进入不安全状态,从而避免死锁(银行家算法)
3.死锁的检测和解除:允许死锁的发生,不过操作系统会负责检测出死锁的发生,然后才去某种措施解除死锁。(资源分配图)
【考点笔记11】资源分配图
顶点结合可以分为两部分:
P=(P1,P2,···,Pn)系统内所有进程组成的集合
R=(r1,r2,···,rn) 系统内所以资源组成的集合
<Pi,ri>: Pi指向ri - -> Pi请求一个ri资源
<ri,Pi>: ri指向Pi - ->ri类资源中的一个资源已分配给进程Pi
在这里插入图片描述当前状态如下:

  • 进程P1已占用两个r1资源,而且正在申请获得一个r2资源。
  • 进程P2已占用一个r2资源和一个r2资源,而且正在申请获得一个r1资源

资源分配图的简化

  • 在分配图中,找出一个既不阻塞又非孤立的进程节点Pi(即从进程集合中找到一个存在连接的边,且资源申请数量小于系统中已有空闲资源数量的进程)。因进程Pi获得了所需要的全部资源,它能继续运行直到完成,然后释放其占有的所有资源(这相当于消去Pi的所有申请边与分配边,使之成为孤立的结点)
  • 进程Pi释放资源后,可以唤醒因等待这些资源而阻塞的进程,原来阻塞的进程可能变为非阻塞进程,根据第一步中的简化方法,消去申请边和分配边。
  • 重复前两步的简化过程后,若能校区图中所有边,使所有进程成为孤立结点,则称图式可完全简化的;若遇到任何过程均不能使该图完全简化,则称该图是不可完全简化的。

可以证明的是:不同简化顺序将得到相同的不可简化图。系统状态S为死锁状态的条件是:当且仅当S状态的资源分配图是不可完全简化的,该定理称为***死锁定理***。

【考点笔记12】银行家算法

死锁的避免

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值