调度算法、进程同步问题
调度算法
操作系统有很多调度算法,大致分为:FSFC(先来先服务)、SJF(短作业优先)、优先级队列算法、响应比优先算法、时间片轮转算法、多级反馈队列算法,这6种。
FSFC(先来先服务)
先来先服务,最简单的算法,不考虑作业的优先级,需要处理的时间等等。
优点:不会出现“饥饿”的情况,适合长作业。
缺点:如果大多是短作业会出现,频繁切换进程的情况。如果是长短作业参差不齐的情况,效率不是很高。
SJF(短作业优先)
会将短作业优先处理,但是会出现“饥饿”的情况。
注:饥饿,指一个任务一直被抢占导致该任务无法被执行。
优先级队列算法
会判断任务的优先级,优先级高的任务会被提前执行。
根据抢占情况区分:
1)非抢占:当cpu正在处理一个作业的时候,有优先级更高的任务过来,任务不会被中断。
2)抢占:优先级更高的时候,cpu会使正在执行的任务中断,执行优先级更高的任务。
根据优先级是否动态区分:
1)静态优先级:任务的优先级不会改变,这种情况会出现“饥饿”。
2)动态优先级:任务可以根据等待时间改变自己的优先级,这样可以避免出现“饥饿”现象。
响应比优先算法
P(响应比)=(等待时间+服务时间)/ 服务时间
根据公式,响应比越高,优先级越高。
刚来的任务响应比都是1的话,则会按照FCFS来执行任务。相同等待的时间,短作业会优先。
如果等待的时间越长,响应比越高优先级越高,克服的饥饿问题,同时兼顾了长作业。
时间片轮转算法
任务会根据指定的时间片执行,如果任务小于时间片会提早释放。
如果长于时间片,则会将任务中断将cpu交给下一个任务。
系统的性能会被时间片的大小所影响,如果时间片太大,则会变成FCFS,如果时间片太小,则会进行频繁的进程切换。
多级反馈队列算法
多级反馈队列是综合了多种算法。
- 任务队列被分为好几个等级
- 如果在第1级里面,任务在规定的时间片里没有被执行完,则会将剩余的任务放入2级队列中
- n+1级队列的时间片是n级时间片的一倍
- 如果一直到第n级任务还没执行完,则会采用时间片轮转的算法。
经典进程同步问题
生产者消费者问题
生产者和消费者之间应该有个盘子。
- 当盘子不满的时候生产者可以放物品进入盘子
- 如果盘子不空的时候消费者可以对盘子进行取物品。
- 消费者和生产者同时只能有一个可以对盘子进行操作。
所以盘子的持有权和盘子的状态就是制约条件。
// 生产者
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 就是盘子还没空的状态
读者-写者问题
一本书,读者和写者都可以对书进行操作。读者可以共享数据,而不修改数据。所以读者可以多个。但是写者只能有一个。
这里有状态的就是:
- 书的拥有权——r w
- 读者人数的修改权——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);
}