EXER2: 完成内核级条件变量和基于内核级条件变量的哲学家就餐问题*
Q1: 给出内核级条件变量的设计描述,并说明其大致执行流程。*
管程相关的数据结构:
// 条件变量
typedef struct condvar{
semaphore_t sem; // 底层实现机制为信号量
int count; // 正在等待条件变量的进程数,为 0 时 signal 为空操作
monitor_t * owner; // 所属管程
} condvar_t;
// 管程
typedef struct monitor{
semaphore_t mutex; // 锁
semaphore_t next; // 因为发出信号而被阻塞的进程等待这个信号量
int next_count; // 因发出信号被阻塞的进程数
condvar_t *cv; // 条件变量
} monitor_t;
管程的 wait 和 signal 操作,wait 用于进程因无法获取所需的资源时将自己阻塞,signal 用于另一个进程释放或生成相关资源后唤醒 wait 的进程。
void
cond_wait (condvar_t *cvp) {
monitor_t *mt = cvp->owner;
cvp->count++;
// 自身开始等待之前现场时唤醒一个进程
if (mt->next_count > 0) {
up(&mt->next); // 当前有因为发出信号而等待的进程,优先唤醒它
} else {
up(&mt->mutex); // 放弃自身对管程的占有权
}
down(&cvp->sem); // 自身进入等待
cvp->count--;
}
void
cond_signal (condvar_t *cvp) {
monitor_t *mt = cvp->owner;
if(cvp->count > 0) {
mt->next_count++;
up(&cvp->sem); // 唤醒,并不是立即开始运行,而是加入就队列
down(&mt->next); // 阻塞自己,等待条件同步
mt->next_count--;
}
}
实现的是 Hoare 管程,进程在发出信号后,下一个在临界区内运行的必须是等待信号的进程。
条件变量实现哲学家就餐问题的过程:
struct proc_struct *philosopher_proc_condvar[N];
int state_condvar[N];
monitor_t mt, *mtp=&mt;
void phi_test_condvar (i) {
if(state_condvar[i] == HUNGRY && state_condvar[LEFT] != EATING
&& state_condvar[RIGHT] != EATING) {
state_condvar[i] = EATING;
cond_signal(&mtp->cv[i]); // 能获取资源则唤醒
}
}
void phi_take_forks_condvar(int i) {
down(&(mtp->mutex));
state[i] = HUNGRY;
phi_test_condvar(i);
if(state_condvar[i] != EATING) {
cond_wait(&mtp->cv[i]); // 如果不能拿,就阻塞自己
}
if(mtp->next_count>0)
up(&(mtp->next));
else
up(&(mtp->mutex));
}
void phi_put_forks_condvar(int i) {
down(&(mtp->mutex));
state[i] = THINKING;
phi_test_condvar(LEFT);
phi_test_condvar(RIGHT);
if(mtp->next_count>0)
up(&(mtp->next));
else
up(&(mtp->mutex));
}
int philosopher_using_condvar(void * arg) {
int i, iter=0;
i=(int)arg;
while(iter++ < TIMES) {
do_sleep(SLEEP_TIME); // 思考
phi_take_forks_condvar(i); // 获取叉子,或阻塞
do_sleep(SLEEP_TIME); // 吃
phi_put_forks_condvar(i); // 放下叉子
}
return 0;
}
Q2: 给出给用户态进程/线程提供条件变量机制的设计方案,并比较说明给内核级提供条件变量机制的异同。*
与练习 1 差不多,可以通过系统调用提供接口,内核检查在管程出入的状态设置。
Q3: 能否不用基于信号量机制来完成条件变量?如果不能,请给出理由,如果能,请给出设计说明和具体实现。*
条件变量维护进程等待队列,可以直接用等待队列和锁机制来完成条件变量。
最后更新: November 26, 2020