操作系统——斯坦福pintos project1测试分析

  • 观察test_priority_donate_one测试代码

观察测试调用的两个函数为获取锁和释放锁。(acquire和release和书本上的含义一样)

分析:

(33行)原进程拥有了lock锁;

(34行)acquire1进程虽然优先级高于原进程,但无法得到lock锁被阻塞,因此,必须将原进程的优先级提升到acquire1的优先级;

(35行)输出结果

(37行)acquire2进程高于原进程,也无法得到lock锁,因此,原进程的优先级应该提升到acquire2的优先级,使原进程运行完释放lock锁。

(40行)原进程释放掉lock锁,acquire2的捐献结束,运行;acquire1的捐献结束,运行;最后原进程运行结束。

再查看测试的正确输出,证明分析的运行思路是正确的:

  • 分析测试priority-donate-multiple

分析:

(35,36行)原进程获取了a和b两个锁。

(38行)原进程创建了a进程,希望得到a锁,虽然a进程优先级高于原进程,但因为a锁被原进程持有,因此a进程堵塞,应该继续运行原进程(优先级=a进程=32);

(42行)原进程创建了b进程,希望得到b锁,虽然优先级高于a进程和原进程,但因为b锁也被原进程持有,因此也应该继续运行原进程,因此原进程(优先级=b进程=33);

(46行)原进程释放b锁,b进程实现抢占,结束对原进程的捐献,b进程运行结束;

b进程已经结束了,接下来还剩a进程和原进程。因为至现在没有释放a锁,a进程即使运行也要被堵塞,因此继续运行原进程(优先级=a进程=32);

(51行)原进程释放a锁,a进程实现抢占,结束对原进程的优先级捐献,a进程运行结束;

(52行)a进程已经运行结束了,原进程(优先级=原来=31)继续运行,输出并结束。

 

再查看测试的正确输出,再来证明分析的运行思路是正确的:

 

 

  • 继续查看priority-donate-multiple2这个测试

可以分析得到a_thread_func和b_thread_func函数都申请传入的锁,而c进程不需要什么锁,直接输出结束的msg提示。

分析:

(41,42行)原进程获得了a锁和b锁;

(44行)原进程创建了一个a进程,a进程希望拥有a锁,虽然其优先级为PRI_DEFAULT + 3,但是a锁被原进程持有,因此a进程被阻塞,捐献优先级给原进程,原进程(优先级=a进程= PRI_DEFAULT + 3)继续运行;

(48行)原进程创建了一个c进程,c进程不需要什么条件运行,优先级为PRI_DEFAULT + 1,但是因为原进程的优先级已经为PRI_DEFAULT + 3,因此c进程并没有运行;

(50行)原进程创建了一个b进程,希望拥有b锁,虽然其优先级为PRI_DEFAULT + 5,但是b锁被原进程持有,因此b进程被阻塞,捐献优先级给原进程,原进程(优先级=b进程= PRI_DEFAULT + 5)继续运行;

(54行)原进程释放a锁,但b进程未对原进程结束捐献,a进程不运行,继续运行原进程(优先级= PRI_DEFAULT + 5);

(58行)原进程释放b锁,b进程抢占运行,结束对原进程的优先级捐赠,b进程运行结束;因此原进程的优先级变为=a进程优先级= PRI_DEFAULT + 3;

继续a进程抢占,结束对原进程的优先级的捐赠,原进程的优先级变为其本身PRI_DEFAULT ;

接下来c进程的优先级为PRI_DEFAULT + 1,抢占,c进程运行结束;

(59行)原进程输出msg语句,原进程运行结束;

 

再查看测试的正确输出,可以得到输出也为b,a,c,原进程的运行顺序,证明分析的运行思路是正确的:

 

  • 继续看测试priority-donate-nest:

 

观察原进程中调用的两个函数,medium_thread_func是希望获得a和b两个锁,一释放a锁就运行yield函数,将进程放入就绪队列;释放b锁后也将进程放入就绪队列;

High_thread_func函数是渴望持有传入的lock锁,并输出,释放结束。

分析:

(39,40行)定义了两个锁,锁a和锁b;

(42行)原进程(low进程)持有了锁a;

(46行)原进程(low进程)创建了一个medium进程,抢占执行了medium_thread_func中并获取了b锁;但是接下来虽然其优先级为PRI_DEFAULT + 1,但是其想要的锁a被原进程持有,因此其阻塞,将优先级捐献给原进程,原进程如今优先级为PRI_DEFAULT + 1;

(47行)原进程将进程放入就绪队列;

(51行)原进程创建了一个high进程,其优先级为PRI_DEFAULT + 2,high进程希望有b锁但是被medium进程持有,因此high进程捐献优先级给medium进程(优先级为PRI_DEFAULT + 2),medium进程捐献优先级给原进程(优先级为PRI_DEFAULT + 2);

(56行)原进程释放a锁,medium进程优先级停止捐献,medium抢占执行并释放a锁,b锁后,high进程抢占执行,停止对medium进程的优先级捐献,执行结束后,medium进程输出结束;

(58行)回到原进程(low进程),执行输出并结束;

 

再查看测试的正确输出,可以得到结束的顺序为high,medium和low,证明分析的运行思路是正确的:

 

  • 继续分析测试priority-donate-sema:

观察分析l_thread_func, m_thread_func和h_thread_func函数:

*l_thread_func函数是希望得到传入的参数的指针指向的锁,并将信号量--,并释放锁;

*m_thread_func函数是将传入参数指针指向的信号量--;

*h_thread_func函数是希望得到传入参数指针指向的锁并将其信号量++,并释放锁。

分析:

(42行)原进程创建了一个low进程,其优先级为PRI_DEFAULT + 1,因此抢占调度,执行l_thread_func,其持有了lock锁,但是sema为0,无法再获得信号量资源,因此被阻塞,其优先级捐赠给原进程,原进程继续运行;

(43行)原进程创建了一个med进程,其优先级为PRI_DEFAULT + 3,而其也渴望拥有sema资源,但sema为0,其被阻塞,也将优先级捐赠给原进程,原进程继续运行;

(44行)原进程创建了一个high进程,其优先级为PRI_DEFAULT + 5,其渴望拥有lock锁,而lock锁被low持有,将优先级捐赠给low进程,原进程继续运行;

(45行)原进程执行sema++,因此触发了low进程,low进程将sema--,并释放了锁;high进程抢占获得锁,并将sema++,释放锁,运行输出结束;接下来运行med进程,sema--,并结束进程。

 

再查看测试的正确输出,可以得到结束的顺序为H,M,L,证明分析的运行思路是正确的:

 

  • 继续分析priority-donate-lower:

*acquire_thread_func函数的意思为得到lock锁和释放lock锁。

分析:

(27行)原进程获取了lock锁;

(28行)原进程创建了一个acquire进程,虽然其优先级为PRI_DEFAULT + 10,但是其需要的lock锁被原进程持有,因此acquire进程将优先级捐赠给原进程,自身阻塞运行;

(33行)原进程的优先级被修改为PRI_DEFAULT + 10-10= PRI_DEFAULT ;acquire进程优先级再次高于原进程,但是同样,其需要的lock锁被原进程持有,因此acquire再次讲优先级捐赠给原进程,自身阻塞运行;(其实就是原进程调用thread_set_priority()函数并不改变其优先级,但是在结束被捐赠后,其优先级应该需要改变)

(36行)原进程释放lock锁,acquire进程抢占运行,得到锁并输出释放锁,运行结束。原进程优先级恢复原来的PRI_DEFAULT -10,运行输出结束;

 

因此观察分析正确的输出结果,证明判断正确:

  • 继续分析priority_sema:

*priority_sema_thread函数就是将sema信号量--;

分析:

(24行)将原进程的优先级设置为PRI_MIN=0;

(25-30行)是一个10次的循环,先来看第一次循环,priority的值为(PRI_DEFAULT-(0+3)%10-1= PRI_DEFAULT-4),之后输出了一句“priority_”空格中为priority的值(即为进程的优先级),之后就创建了一个以priority值为优先级的进程;

 

观察priority的值的变化:

从i=0:PRI_DEFAULT-4;

i=1:PRI_DEFAULT-5;

i=2:PRI_DEFAULT-6,……逐渐递减,至PRI_DEFAULT-10;

直至i=7时,priority= PRI_DEFAULT-1;

i=8:PRI_DEFAULT-2;

i=9:PRI_DEFAULT-3;

这边进程的运行是所有的进程优先级都比原进程高,但是都没有办法得到sema信号量,因此原进程继续运行;

(33行)也是一个for循环,每次都将sema信号量++;

第一次信号量++的时候,priority= PRI_DEFAULT-1的进程优先运行;即每个进程按照其优先级依次结束;

(说明信号量等待队列时属于优先级队列)

因此观察分析正确的输出结果,证明判断正确:

 

  • 再看priority-condvar测试:

*priority_condvar_thread()函数的操作为得到lock锁;

再来看cond_wait()函数:

先来明确semaphore_elem, condition 结构体的内容:

*Semaphore_elem结构体中存储的是一个在队列中的信号量;

*condition结构体中存储的是一个等待队列;

因此,分析可得cond_wait()函数为将lock锁释放,并且等待信号量--,再申请得到lock锁;

其次,再来看cond_signal()函数,其作用类似于signal()函数,为当等待队列中不为空时,将其信号量++,唤醒进程;

分析:

(27行)原进程的优先级被设置为PRI_MIN;

(28-34行)其为一个for循环,每次priority的值为i=0: PRI_DEFAULT - (i + 7) % 10 – 1= PRI_DEFAULT-8;

i=1: PRI_DEFAULT-9;

….

i=3: PRI_DEFAULT-1;

i=4: PRI_DEFAULT-2;

创建10个名字为“priority+优先级”的进程,每个进程都调用了 acquire函数得到了lock锁,之后又调用cond_wait()函数释放了锁,但都阻塞在信号量--语句上;

因此,原进程继续运行;

(36-42行)其也是一个for循环,每次都先得到lock锁,防止其他进程抢占,接下来调用cond_signal()函数,将信号量++,然后最高优先级的进程运行,最后释放lock锁,因此整个过程是10个进程根据其优先级运行输出结束;

(说明condition的等待队列为优先级队列)

因此观察分析正确的输出结果,证明判断正确:

 

  • 接下来看最后一个测试priority-donate-chain:

前情提要:

先了解测试中调用的常量,结构体和函数:

*NESTING_DEPTH常量为8;

*Lock_pair结构体内部为两个lock锁指针;

*donor_thread_func函数为得到以传入locks结构体中的第一个指针指向的lock锁,并得到第二个指针指向的lock锁;输出msg后,再释放第一个指针指向的lock锁。

*interloper_thread_func函数只是一个普普通通的输出进程名字的函数。

 

然后正式开始分析主函数:

分析:

(54行)原进程将自己的优先级设置为PRI_MIN=0;

(56-57行)其为一个7次的for循环,对于每个进程的lock数组初始化;

(59行)原进程得到了lock[0]的锁;

(62-78行)其为对1-7进程的循环操作。设置每个priority+i的进程的优先级为3*i,并设置lock_pairs[]数组的值,lock_pairs[i]的值为,first指针为locks[i]的锁,second指针为locks[i-1]的锁(循环连接);之后每个循环都创建了一个interloper+i的进程,每个的优先级都=priority i的优先级-1;

之后创建线程,传入lock_pairs[i],手动模拟一步priority3即创建的第一个进程:

Ⅰ Priority1进程调用donor_thread_func函数,得到了lock[1]锁,再想lock[0]锁的时候,发现lock[0]锁被原进程持有,因此priority1进程将优先级捐赠给原进程,原进程继续运行;

Ⅱ 同样的创建了priority2进程,其优先级高,抢占的进入donor_thread_func函数,得到了lock[2]锁,渴望也得到lock[1]锁,发现lock[1]锁被priority2进程占有,因此priority2捐赠优先级给priority1,依次给原进程;

……同样最后一个进程priority7

Priority7的first指针指向NULL,second指针指向前一个锁,因此,其也同样在想得到lock[6]锁的时候被阻塞,至此所有进程的优先级逐级捐赠,依然是原进程继续运行;

(80行)原进程释放lock[0]锁,priority1,priority2……priority7逐级运行结束,(因为优先级捐赠,只要没有释放完priority7需要的锁,他们的优先级都为priority7的优先级)

 

最后所有解锁问题结束,才按优先级,逐次结束interloper i和priority i的14个进程。

 

因此观察分析正确的输出结果,证明判断正确:

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值