移动操作系统内核分析--基于工作者线程实现,要求在系统调用中使用 “完成变量”等待提交的工作完成后(内核线程信息打印完成后)再返回。

思考题:

1、如何避免死锁?

可以通过破坏死锁产生的4个必要条件来 预防死锁,由于资源互斥是资源使用的固有特性是无法改变的。

Ⅰ、破坏不可剥夺条件:一个进程不能获得所需要的全部资源时便处于等待状态,等待期间他占有的资源将被隐式的释放重新加入到 系统的资源列表中,可以被其他的进程使用,而等待的进程只有重新获得自己原有的资源以及新申请的资源才可以重新启动,执行。

Ⅱ、破坏请求与保持条件:第一种方法静态分配即每个进程在开始执行时就申请他所需要的全部资源。第二种是动态分配即每个进程在申请所需要的资源时他本身不占用系统资源。

Ⅲ、破坏循环等待条件:采用资源有序分配其基本思想是将系统中的所有资源顺序编号,将紧缺的,稀少的采用较大的编号,在申请资源时必须按照编号的顺序进行,一个进程只有获得较小编号的进程才能申请较大编号的进程。

 

2、读写锁中如何避免写者或读者被饿死?

Linux用一个整数counter代表一个rwlock。0代表没有人占有锁,-1代表有一个线程持有着写锁,正整数n代表有n个线程持有读锁。要拿读锁时,如果counter小于0,则继续循环测试,直到counter非负。然后给counter加1,拿锁成功。(当然,得保证“在counter非负的情况下加1”这个操作的原子性,一般通过spinlock或者bit spinlock实现)。如果已经有一个线程拿着读锁还未释放,另一个线程获取读锁会立即成功。

不过存在公平性的问题:写者可能会被饿死。如果有很多线程相续拿到读锁然后释放读锁,保持counter的值始终大于0,那写者就一直拿不到写锁。

解决的一个方法是在rwlock元数据中增加一个标记,代表是否有写者在等待读者。读者要拿读锁时,先要等待这个标记的清除。更加先进的方法,是让等待者排一个FIFO队列,比较著名的是MCS lock和CLH lock。

Ⅰ、避免写者饿死:

写者优先的优先性体现在一批读者的写操作上,就类似于当有写者在执行写操作,后面有等待写的写者,则读者会一直等待。要实现以下目标,可以使得写者优先:

①要让读者与写者之间、以及写者与写者之问要互斥地访同数据集;

②在无写进程到来时各读者可同时访问数据集;

③在读者和写者都等待时访问时写者优先

Ⅱ、避免读者饿死:

有一个字段,写者尝试加锁的时候,就减去0x1000000,读者加锁的时候,就尝试减去1,只要非负就加锁成功。

 

作业题目:

前次作业中我们在系统调用里提交一个工作(打印内核线程信息)到workqueue中,让内核的工作者线程去做。本次作业基于这一实现,要求在系统调用中使用

“完成变量”等待提交的工作完成后(内核线程信息打印完成后)再返回。

 

实现代码图:

运行输出图:

发布了12 篇原创文章 · 获赞 2 · 访问量 1552

猜你喜欢

转载自blog.csdn.net/hongweisong666/article/details/103193442