Xv6内核分析(十一)

gewenbin
gewenbin
gewenbin
188
文章
15
评论
2020年12月20日17:55:45 评论 438

sleep与wakeup分析

1. 案例

首先来看下xv6的sleep和wakeup使用例子:

cquire(lock)
sleep(chan,lock)
release(lock)
 
acquire(lock)
wakeup(chan)
release(lock)

可以看出,在xv6下使用sleep和wakeup时必须要锁将这两个接口保护起来。

2. sleep函数

Xv6内核分析(十一)

  • 检查sleep接口中的锁是否存在。
  • 检查此锁是否是保护进程表的锁,如果是,则表明在调用sleep的时候已经被ptable.lock锁保护住,那么就继续执行;如果不是,那么由于要修改进程表中的数据,所以需要获取进程表锁,当获取了进程表锁后,sleep就被进程表保护了,那么之前的锁就可以释放了。
  • 修改进程的状态为休眠态。
  • 调用sched()函数切换到内核scheduler线程。

sched函数如下:

Xv6内核分析(十一)

从代码可以看出,调用sched()函数之前需要满足以下几个条件:

  1. 需要持有ptable.lock。
  2. 进程状态必须是非运行态。
  3. 处理器必须是关中断状态。

其中处理器关中断状态是通过acquire接口间接实现的,因为acquire接口实现会关闭中断。

接着调用swtch()函数切换到内核schduler线程,回头来看看schduler线程:

Xv6内核分析(十一)

schduler线程再次运行时,从switchkvm开始运行,然后选出下一个线程运行,从而可以看出,不管是内核scduler线程还是通过sched调用swtch()函数,前后都是获取和释放ptable.lock。

3. wakeup函数

Xv6内核分析(十一)

wakeup的逻辑很简单,就是到进程表中寻找满足以下两个条件的进程:

  • 状态时睡眠状态的进程。
  • 进程中记录的chan和wakeup传进来的相同的进程。

从代码中可以看出,当调用完wakeup之后,只是将进程的状态改成可运行,并没有立即切换到新进程运行。下一个调度点应该是tick中断中调度运行的。

gewenbin
  • 本文由 发表于 2020年12月20日17:55:45
  • 转载请务必保留本文链接:http://www.databusworld.cn/9476.html
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: