<操作系统导论>第三十一章

1. The fifirst problem is just to implement and test a solution to the fork/join problem, as described in the text. Even though this solution is described in the text, the act of typing it in on your own is worthwhile; even Bach would rewrite Vivaldi, allowing one soon-to-be master to learn from an existing one. See fork-join.c for details. Add the call sleep(1) to the child to ensure it is working.
第一个问题就是实现和测试 fork/join 问题的解决方案,如本文所述。 即使在文本中描述了此解决方案,重新自己实现一遍也是值得的。 even Bach would rewrite Vivaldi,allowing one soon-to-be master to learn from an existing one。有关详细信息,请参见 fork-join.c。 将添加 sleep(1) 到 child 函数内以确保其正常工作。

在这里插入图片描述在这里插入图片描述在这里插入图片描述

2. Let’s now generalize this a bit by investigating the rendezvous problem. The problem is as follows: you have two threads, each of which are about to enter the rendezvous point in the code. Neither should exit this part of the code before the other enters it. Consider using twosemaphores for this task, and see rendezvous.c for details.
现在,我们通过研究集合点问题 rendezvous problem 来对此进行概括。 问题如下:您有两个线程,每个线程将要在代码中进入集合点。 任何一方都不应在另一方进入之前退出代码的这一部分。 该任务使用两个信号量,有关详细信息,请参见 rendezvous.c。

想要先打印两个before再打印两个after

在这里插入图片描述在这里插入图片描述在这里插入图片描述

4. Now let’s solve the reader-writer problem, also as described in the text. In this fifirst take, don’t worry about starvation. See the code in reader-writer.c for details. Add sleep() calls to your code to demonstrate it works as you expect. Can you show the existence of the starvation problem?
现在按照文本中所述,解决读者写者问题。 首先,不用考虑进程饥饿。 有关详细信息,请参见 reader-writer.c 中的代码。 将 sleep()调用添加到您的代码中,以证明它可以按预期工作。 你能证明饥饿问题的存在吗?

在这里插入图片描述
在这里插入图片描述

typedef struct __rwlock_t {
	sem_t lock;
	sem_t write_lock;
	int reader_number;
} rwlock_t;


void rwlock_init(rwlock_t *rw) {
	sem_init(&rw->lock,0,1);
	sem_init(&rw->write_lock,0,1);
	rw->reader_number=0;
}

void rwlock_acquire_readlock(rwlock_t *rw) {
	sleep(1);
	sem_wait(&rw->lock);
	rw->reader_number++;
	if(rw->reader_number==1){
	    sem_wait(&rw->write_lock);
	}
	sem_post(&rw->lock);
}

void rwlock_release_readlock(rwlock_t *rw) {
	sem_wait(&rw->lock);
	rw->reader_number--;
	if(rw->reader_number==0){
	    sem_post(&rw->write_lock);
	}
	sem_post(&rw->lock);
}

void rwlock_acquire_writelock(rwlock_t *rw) {
	sleep(1);
	sem_wait(&rw->write_lock);
}

void rwlock_release_writelock(rwlock_t *rw) {
	sleep(1);
	sem_wait(&rw->write_lock);
}

./reader-writer 5 5 10
程序三个参数分别为读者数,写者数,每个读者、写者进行的读写操作数
当读者数量远大于写者时,写者可能饿死,读者不需要锁就能进入临界区,只要有一个读者获得锁,
其他读者线程就能运行,读者数量可能一直大于0,而写者始终无法获取锁
运行结果:
在这里插入图片描述

5. Let’s look at the reader-writer problem again, but this time, worry about starvation. How can you ensure that all readers and writers eventually make progress? See reader-writer-nostarve.c for details.
让我们再次看一下读者写者问题,但这一次需要考虑进程饥饿。 您如何确保所有读者和写者运行? 有关详细信息,请参见 reader-writer-nostarve.c。

在这里插入图片描述
在这里插入图片描述

typedef struct __rwlock_t {
	sem_t lock;
	sem_t write_lock;
	sem_t write_waiting;
	int reader_number;
} rwlock_t;


void rwlock_init(rwlock_t *rw) {
	sem_init(&rw->lock,0,1);
	sem_init(&rw->write_lock,0,1);
	sem_init(&rw->write_waiting,0,1);
	rw->reader_number=0;
}

void rwlock_acquire_readlock(rwlock_t *rw) {
	sleep(1);
	sem_wait(&rw->write_waiting);
	sem_wait(&rw->lock);
	rw->reader_number++;
	if(rw->reader_number==1){
	    sem_wait(&rw->write_lock);
	}
	sem_post(&rw->lock);
	sem_post(&rw->write_waiting);
}

void rwlock_release_readlock(rwlock_t *rw) {
	sem_wait(&rw->lock);
	rw->reader_number--;
	if(rw->reader_number==0){
	    sem_post(&rw->write_lock);
	}
	sem_post(&rw->lock);
}

void rwlock_acquire_writelock(rwlock_t *rw) {
	sleep(1);
	sem_wait(&rw->write_waiting);
	sem_wait(&rw->write_lock);
	sem_post(&rw->write_waiting);
}

void rwlock_release_writelock(rwlock_t *rw) {
	sem_post(&rw->write_lock);
}


新增 write_waiting 锁,写者读者都需要竞争这个锁。新增读者要持有这把锁,写者进行写也要持有这把锁,一旦写者抢到了这把锁,就不能增加新读者,直到写者完成写。
在这里插入图片描述
运行指令:./reader-writer-nostarve 5 5 10

在这里插入图片描述
在这里插入图片描述
6. Use semaphores to build a no-starve mutex, in which any thread that tries to acquire the mutex will eventually obtain it. See the code in mutex-nostarve.c for more information.
使用信号量构建一个没有饥饿的互斥量,其中任何试图获取该互斥量的线程都将最终获得它。 有关更多信息,请参见 mutex-nostarve.c 中的代码。

释放临界区锁后,确认所有线程都执行过临界区后再继续执行

在这里插入图片描述

typedef __ns_mutex_t {
sem_t mutex;
sem_t barrier;
sem_t lock;
int num_threads;
} ns_mutex_t;

ns_mutex_t m;
void ns_mutex_init(ns_mutex_t *m,int num_threads) {
sem_init(&m->barrier,0,-num_threads+1);
sem_init(&m->metux,0,1);
}

void ns_mutex_acquire(ns_mutex_t *m) {
sem_wait(&m->lock);
}

void ns_mutex_release(ns_mutex_t *m) {
sem_post(&m->lock);
sem_post(&m->barrier);
sem_wait(&m->barrier);
sem_wait(&m->mutex);
for(int i=0;i<m->num_threads;i++){
sem_post(&m->barrier);
}
sem_post(&m->mutex);
}


代码还是有点问题,搞不好了

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值