[No00003D]操作系统Operating Systems信号量的代码实现Coding Semaphore &死锁处理Deadlock
操作系统Operating Systems信号量的代码实现Coding Semaphore &死锁处理Deadlock
可以操刀了—从纸上到实际
从Linux 0.11 那里学点东西…
读磁盘块
bread(int dev,int block){
struct buffer_head * bh;
ll_rw_block(READ,bh);
wait_on_buffer(bh);
启动磁盘读以后睡眠,等待磁盘读完由磁盘中断将其唤醒,也是一种同步
lock_buffer(buffer_head*bh)
{cli();
while(bh->b_lock)???
sleep_on(&bh->b_wait);
bh->b_lock = 1;
sti(); }
void sleep_on(struct task_struct **p){
struct task_struct *tmp;
tmp = *p;
*p = current;
current->state = TASK_UNINTERRUPTIBLE;
schedule();
if (tmp)
tmp->state=0;}
Linux 0.11 sleep_on形成的队列
sleep_on(struct task_struct **p) p 是一个指向task_struct 结构体的指针的指针
如何从Linux 0.11 的这个队列中唤醒?
static void read_intr(void){
... 磁盘中断
end_request(1);
end_request(int uptodate){
...
unlock_buffer(CURRENT->bh);
unlock_buffer(struct buffer_head * bh){
bh->b_lock=0;
wake_up(&bh->b_wait);}
schedule();
if (tmp)
tmp->state=0; 这是sleep_on 的最后三句
wake_up(struct task_struct **p){
if (p && *p) {
(**p).state=0; *p=NULL;}}
死锁处理Deadlock
死锁的成因
资源 互斥使用,一旦占有别人无法使用
进程 占有 了一些资源,又不释放,再去 申请 其他资源
各自占有的资源和互相申请的资源形成了环路等待
死锁的4个必要条件
互斥使用(Mutual exclusion)
资源的固有特性, 如道口
不可抢占(No preemption)
资源只能自愿放弃, 如车开走以后
请求和保持(Hold and wait)
进程必须占有资源,再去申请
循环等待(Circular wait)
在资源分配图中存在一个环路
死锁处理方法概述
死锁预防 "no smoking" ,预防火灾
破坏死锁出现的条件
死锁避免 检测到煤气超标时,自动切断电源
检测每个资源请求,如果造成死锁就拒绝
死锁检测+ 恢复 发现火灾时,立刻拿起灭火器
检测到死锁出现时,让一些进程回滚,让出资源
死锁忽略 在太阳上可以对火灾全然不顾
就好像没有出现死锁一样
死锁预防的方法例子
在进程执行前, 一次性申请所有需要的资源, 不会占有资源再去申请其它资源
缺点1: 需要预知未来,编程困难
缺点2: 许多资源分配后很长时间后才使用,资源利用率低
对资源类型进行排序, 资源申请必须按序进行 ,不会出现环路等待
缺点: 仍然造成资源浪费
死锁避免: 判断此次请求是否引起死锁?
如果系统中的所有进程存在一个可完成的执行序列P 1 ,…P n ,则称系统处于安全状态
都能执行完成当然就不死锁
找安全序列的银行家算法(Dijkstra 提出)
int Available[1..m]; // 每种资源剩余数量
int Allocation[1..n,1..m]; // 已分配资源数量
int Need[1..n,1..m];// 进程还需的各种资源数量
int Work[1..m]; // 工作向量
bool Finish [1..n]; // 进程是否结束
Work = Available; Finish[1..n] = false;
while(true){
for(i=1; i<=n; i++){
if(Finish[i]==false && Need[i]≤Work){
Work = Work + Allocation[i];
Finish[i] = true; break;} //T(n)=O(mn 2 )
else {goto end;}
}
}
End: for(i=1;i<=n;i++)
if(Finish[i]==false) return "deadlock";
死锁避免之银行家算法实例
请求出现时:首先假装分配,然后调用银行家算法
P 0 申请(0,2,0)
进程P 0 , P 1 , P 2 , P 3 , P 4 一个也没法执行,死锁进程组
此次申请被拒绝
死锁检测+ 恢复: 发现问题再处理
基本原因: 每次申请都执行O(mn 2 ) ,效率低。 发现问题再处理
定时检测或者是发现资源利用率低时检测
Finish[1..n] = false;
if(Allocation[i] == 0) Finish[i]=true;
...// 和Banker 算法完全一样
for(i=1;i<=n;i++)
if(Finish[i]==false)
deadlock = deadlock + {i};
选择哪些进程回滚? 优先级? 占用资源多的? …
如何实现回滚? 那些已经修改的文件怎么办?
到此:提供以前所有操作系统 doc下载