操作系统——系统调度算法、经典进程同步问题

本文详细介绍了操作系统中的几种调度算法,包括FSFC(先来先服务)、SJF(短作业优先)、优先级队列算法、响应比优先算法、时间片轮转算法和多级反馈队列算法,并探讨了它们的优缺点。此外,还讨论了经典进程同步问题,如生产者消费者问题、读者-写者问题、哲学家进餐问题和吸烟者问题,解析了这些问题的解决方案和关键制约条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

调度算法

操作系统有很多调度算法,大致分为:FSFC(先来先服务)、SJF(短作业优先)、优先级队列算法、响应比优先算法、时间片轮转算法、多级反馈队列算法,这6种。

FSFC(先来先服务)

先来先服务,最简单的算法,不考虑作业的优先级,需要处理的时间等等。
优点:不会出现“饥饿”的情况,适合长作业。
缺点:如果大多是短作业会出现,频繁切换进程的情况。如果是长短作业参差不齐的情况,效率不是很高。

SJF(短作业优先)

会将短作业优先处理,但是会出现“饥饿”的情况。
注:饥饿,指一个任务一直被抢占导致该任务无法被执行。

优先级队列算法

会判断任务的优先级,优先级高的任务会被提前执行。
根据抢占情况区分:
1)非抢占:当cpu正在处理一个作业的时候,有优先级更高的任务过来,任务不会被中断。
2)抢占:优先级更高的时候,cpu会使正在执行的任务中断,执行优先级更高的任务。
根据优先级是否动态区分:
1)静态优先级:任务的优先级不会改变,这种情况会出现“饥饿”。
2)动态优先级:任务可以根据等待时间改变自己的优先级,这样可以避免出现“饥饿”现象。

响应比优先算法

P(响应比)=(等待时间+服务时间)/ 服务时间
根据公式,响应比越高,优先级越高。
刚来的任务响应比都是1的话,则会按照FCFS来执行任务。相同等待的时间,短作业会优先。
如果等待的时间越长,响应比越高优先级越高,克服的饥饿问题,同时兼顾了长作业。

时间片轮转算法

任务会根据指定的时间片执行,如果任务小于时间片会提早释放。
如果长于时间片,则会将任务中断将cpu交给下一个任务。
系统的性能会被时间片的大小所影响,如果时间片太大,则会变成FCFS,如果时间片太小,则会进行频繁的进程切换。

多级反馈队列算法

在这里插入图片描述
多级反馈队列是综合了多种算法。

  1. 任务队列被分为好几个等级
  2. 如果在第1级里面,任务在规定的时间片里没有被执行完,则会将剩余的任务放入2级队列中
  3. n+1级队列的时间片是n级时间片的一倍
  4. 如果一直到第n级任务还没执行完,则会采用时间片轮转的算法。

经典进程同步问题

生产者消费者问题

生产者和消费者之间应该有个盘子。

  1. 当盘子不满的时候生产者可以放物品进入盘子
  2. 如果盘子不空的时候消费者可以对盘子进行取物品。
  3. 消费者和生产者同时只能有一个可以对盘子进行操作。

所以盘子的持有权和盘子的状态就是制约条件。

// 生产者
p(notFull);
p(mutex);
put put put
v(mutex);
v(notEmpty);

// 消费者
p(notEmpty);
p(mutex);
get get get
v(mutex);
v(notFull);

上面的 notFull 就是盘子还没满的状态,mutex是盘子的操作权限,notEmpty 就是盘子还没空的状态

读者-写者问题

一本书,读者和写者都可以对书进行操作。读者可以共享数据,而不修改数据。所以读者可以多个。但是写者只能有一个。
这里有状态的就是:

  1. 书的拥有权——r w
  2. 读者人数的修改权——mutex
// 写者
P(rw)
write write write
v(rw)

// 读者
p(mutex)
if(count == 0)
	p(rw) // 如果是第一个读者,说明可能有写者拥有书的权限,等待读写锁
count++;
v(mutex)

read read read

p(mutex)
count--;
if(count == 0) // 是最后一个读者的话,就释放rw锁
	v(rw)
v(mutex)		
	

哲学家进餐问题

在这里插入图片描述
一共有5个哲学家吃饭,只有1个人拿起桌上的2只筷子才能吃饭。但是桌子上只有5只筷子。
如果每个人拿1只,这样每个人都只能等待其他人吃完放下筷子,但是永远都等不到,所以这就进入了无限等待(死锁)的情况。

所以可以让 奇数编号的哲学家拿左手边的筷子,偶数编号的哲学家拿右手边的筷子
规定:编号i的筷子在编号i哲学家的左边
例子:0号哲学家需要拿0号筷子和4号筷子

semaphore chopstick[5] = {1,1,1,1,1};
if(i%2!=0) {
	p(chopstick[i]);
	p(chopstick[(i+4)%5]);	
} else {
	p(chopstick[(i+4)%5]);
	p(chopstick[i]);
}
	eat eat eat
if(i%2!=0) {
	v(chopstick[(4+i)%5]);
	v(chopstick[i]);
	
} else {
	v(chopstick[i]);
	v(chopstick[(i+4)%5]);
}	

吸烟者问题

假设一个系统有三个抽烟者进程和一个供应者进程。每个抽烟者不停地卷烟 并抽掉它,但是要卷起并抽掉一支烟,抽烟者需要有三种材料:烟草、纸和胶水。三个抽烟 者中,第一个拥有烟草、第二个拥有纸,第三个拥有胶水。供应者进程无限地提供三种材料, 供应者每次将两种材料放到桌子上,拥有剩下那种材料的抽烟者卷一根烟并抽掉它,并给供 应者一个信号告诉完成了,供应者就会放另外两种材料在桌上,这种过程一直重复(让三个 抽烟者轮流地抽烟)。

int random; //存储随机数
semaphore offer1=0; //定义信号量对应烟草和纸组合的资源
semaphore offer2=0; //定义信号量对应烟草和胶水组合的资源
semaphore offer3=0; //定义信号量对应纸和胶水组合的资源
semaphore finish=0; //定义信号量表示抽烟是否完成

//供应者
while(1){
    random = 任意一个整数随机数;
    random=random% 3;
    if(random==0)
        V(offerl) ; //提供烟草和纸
    else if(random==l) 
        V(offer2);  //提供烟草和胶水
    else
        V(offer3)  //提供纸和胶水
    // 任意两种材料放在桌子上;
    P(finish);
}

//拥有烟草者
while(1){
    P (offer3);
    // 拿纸和胶水,卷成烟,抽掉;
    V(finish);
}

//拥有纸者
while(1){
    P(offer2);
    // 烟草和胶水,卷成烟,抽掉;
    V(finish);
}

//拥有胶水者
while(1){
    P(offer1);
    // 拿烟草和纸,卷成烟,抽掉;
    v(finish);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值