ucore-lab7

2024-04-02 13:58
文章标签 lab7 ucore

本文主要是介绍ucore-lab7,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

练习1 理解内核级信号量的实现和基于内核级信号量的哲学家就餐问题

完成练习0后,建议大家比较一下(可用kdiff3等文件比较软件)个人完成的lab6和练习0完成后的刚> 修改的lab7之间的区别,分析了解lab7采用信号量的执行过程。执行make grade,大部分测试用应该通过。

[练习1.1]请在实验报告中给出内核级信号量的设计描述,并说其大致执行流流程。

答: 在ucore中,通过sem.h,sem.c实现了信号量。
其中,信号的数据结构是这样的:
int value;
wait_queue_t wait_queue;
对于V操作和P操作,分别用up和down函数来对应。

down()函数:
开中断,首先对sem.value >0 ,对sem.value减1,关闭中断,proc可以获得相应的资源。如果sem.value <= 0,那么就需要将proc放入等待队列,并进行调度 schedule(),直到别的占用此资源的proc释放该资源并唤醒等待的proc, wait_current_del(&(sem->wait_queue)在等待队列中删除wait wait);

up()函数:
首先关中断,检查sem.wait_queue是否为空,如果为空,说明没有在等待此资源的proc,所以将sem.value加1;如果不为空,那么说明有proc在等待此资源,那么唤醒该proc,开中断。
其中关中断是通过local_intr_save(intr_flag);实现的,这个函数只是保存了一些中断的变量,尝试去关闭中断,如果中断已经关闭,则不执行。
local_intr_restore(intr_flag);使能中断。

[练习1.2]请在实验报告中给出给用户态进程/线程提供信号量机制的设计方案,并比较说明给内核级提供信号量机制的异同。

答:用户态的进行/线程的信号量的数据结构和内核级的是一样的。
对于用户态的线程/进程使用信号量机制,应该首先通过系统调用进行sem的初始化,设置sem.value以及sem.wait_queue,而在初始化之后,在使用这个信号量时,通过P操作与V操作,也是通过系统调用进入到内核中进行处理,简称是否等待或者释放资源。
不同: 在用户态使用信号量时,需要进行系统调用进入到内核态进行操作。

练习2 完成内核级条件变量和基于内核级条件变量的哲学家就餐问题

首先掌握管程机制,然后基于信号量实现完成条件变量实现,然后用管程机制实现哲学家就餐问题的解决方案(基于条件变量)。

[练习2.1]请在实验报告中给出内核级条件变量的设计描述,并说其大致执行流流程。

答:数据结构如下:

typedef struct condvar{semaphore_t sem; //表示等待的队列int count; //等待的队列的数目monitor_t * owner; //相对应的管程
}condvar_t;
typedef struct monitor{semaphore_t mutex;  //互斥量semaphore_t next; //用来实现Hoare机制int next_count; condvar_t * cv; //条件变量
}monitor_t;    

monitor_init()、cond_signal()、cond_wait()函数。

  • monitor_init()函数:

    对条件变量进行初始化,设置next_count为0,对mutex,next进行初始化, sem_init(&(mtp->mutex), 1); //unlocked
    并分配num个condvar_t,设置cv的count为0,初始化cv的sem和owner。

    for(i=0; i<num_cv; i++){mtp->cv[i].count=0;
    sem_init(&(mtp->cv[i].sem),0);
    mtp->cv[i].owner=mtp;
    }
    

  • cond_signal()函数: 唤醒睡在条件变量上的线程

    如果cv的count>0,说明有proc在等待,那么需要唤醒等待在cv.sem上的proc,并使自己进行睡眠,同时monitor.next_count++,在被唤醒后执行monitor.next_count–;如果cv的count == 0,说明没有proc在等待cv.sem,直接返回函数。

    for(i=0; i<num_cv; i++){if(cvp ->count > 0){
    cvp->owner -> next_count ++;
    up(&(cvp->sem));
    down(&(cvp -> owner->next));//这就是Hoare机制,直接切换回等待条件变量的进程,等其执行完毕,这个线程才能执行 count--
    cvp -> owner -> next_count --;}
    


    Hansen机制:

    if(cvp ->count > 0){ 
    up(&(cvp->sem));
    }
    


    其中另外一种机制是Hansen机制:

  • cond_wait()函数:使线程睡在条件变量上

    先将cv.count++,如果monitor.next_count >0,说明有进程执行cond_signal()函数并且睡着了,此时唤醒此proc;否则的话,说明目前没有因为执行了cond_signal()函数的proc睡着,此时唤醒因为互斥条件mutex无法进入管程的proc。在这之后,使A在cv.sem上进行等待并进行调度,如果A睡醒了,则cv.count–。

    cvp -> count ++;等待的进程数目+1
    if(cvp -> owner->next_count > 0){up(&(cvp -> owner -> next)); //唤醒另一个给出条件变量的进程}
    else{
    up(&(cvp -> owner -> mutex));  //释放mutex,是其他进程得到monitor进入管程
    }
    down(&(cvp -> sem)); //等待,在sem
    cvp -> count --; //等待的数目-1
    

    Hansen机制

    //wait 的时候,等待的进程数+1,然后wait在sem上,释放mutex
    cvp->count++;
    up(&cvp->owner->mutex);
    down(&cvp->sem);
    //上锁,count -1
    down(&cvp->owner->mutex);
    cvp->count--;
    


    哲学家问题

信号量的实现:

semphore_t mutex 临界区互斥信号量

semphore_t s[N] 每个哲学家一个信号量

试图得到叉子

首先判断左右的状态不是“eatting”然后是自己的状态变成“EATING” up(s[i]);

拿叉子

down(&mutex)进入临界区
state_sema[i]=HUNGRY 记录饥饿
试图得到叉子如果得到up(s[i])
up(&mutex)离开临界区
down(&s[i])如果得不到叉子就等待

放叉子

down(&mutex)进入临界区
state_sema[i]=THINKING 改变状态为就餐结束
phi_test_sema(LEFT)看左邻局能否进餐
phi_test_sema(RIGHT)看一下右邻居能否进餐
up(&mutex)离开临界区

管程的实现

数据结构:
struct proc_struct *philosopher_proc_condvar[N]; // N philosopher
int state_condvar[N]; // the philosopher’s state: EATING, HUNGARY, THINKING
monitor_t mt, *mtp=&mt; // monitor

试图得到叉子

void phi_test_condvar (i) { 
if(state_condvar[i]==HUNGRY&&state_condvar[LEFT]!=EATING&&state_condvar[RIGHT]!=EATING) {cprintf("phi_test_condvar: state_condvar[%d] will eating\n",i);state_condvar[i] = EATING ;cprintf("phi_test_condvar: signal self_cv[%d] \n",i);cond_signal(&mtp->cv[i]) ; //得到条件变量cv[i]
}
}


拿叉子

void phi_take_forks_condvar(int i) {down(&(mtp->mutex));  //进入管程的临界区
//--------into routine in monitor--------------// LAB7 EXERCISE1: 2013011424// I am hungry// try to get fork
//--------leave routine in monitor--------------state_condvar[i] =  HUNGRY; //改变状态为 HUNGRYphi_test_condvar(i); //试图拿到叉子 if(state_condvar[i] != EATING){cond_wait(&mtp -> cv[i]);}if(mtp->next_count>0) //Hoare机制up(&(mtp->next));elseup(&(mtp->mutex));
}

放叉子

void phi_put_forks_condvar(int i) {down(&(mtp->mutex));//进入临界区//--------into routine in monitor--------------// LAB7 EXERCISE1: 2013011424// I ate over// test left and right neighbors
//--------leave routine in monitor--------------state_condvar[i] = THINKING; 改变状态为THINKINGphi_test_condvar( LEFT); //左边的得到叉子phi_test_condvar(RIGHT); //右边的得到叉子if(mtp->next_count>0)up(&(mtp->next));elseup(&(mtp->mutex)); //离开临界区
}


[练习2.2]请在实验报告中给出给用户态进程/线程提供条件变量机制的设计方案,并比较说明给内核级提供条件变量机制的异同。

用户级别的的管程,则通过初始化condvar 然后通过系统调用在用户级别实现管程的处理函数。不同点:用户需要系统调用。

这篇关于ucore-lab7的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/870168

相关文章

6.S081的Lab学习——Lab7: Multithreading

文章目录 前言一、Uthread: switching between threads (moderate)提示:解析 二、Using threads (moderate)解析: 三、Barrier (moderate)解析: 总结 前言 一个本硕双非的小菜鸡,备战24年秋招。打算尝试6.S081,将它的Lab逐一实现,并记录期间心酸历程。 代码下载 官方网站:6.S081

ucore_lab7

练习1 理解内核级信号量的实现和基于内核级信号量的哲学家就餐问题 完成练习0后,建议大家比较一下(可用kdiff3等文件比较软件)个人完成的lab6和练习0完成后的刚> 修改的lab7之间的区别,分析了解lab7采用信号量的执行过程。执行make grade,大部分测试用应该通过。 [练习1.1]请在实验报告中给出内核级信号量的设计描述,并说其大致执行流流程。 答: 在ucore中,通

【Ucore操作系统】6. 文件系统与I/O重定向

文章目录 【 0. 引言 】【 1. 文件系统接口 】1.1 文件和目录1.1.1 常规文件1.1.2 目录1.1.3 文件系统 1.2 简易文件与目录抽象1.3 打开文件与读写文件的系统调用1.3.1 文件的打开1.3.2 文件的顺序读写 【 2. nfs 文件系统 】2.1 文件系统布局2.2 virtio 磁盘驱动2.3 磁盘块缓存2.4 inode的操作2.5 文件在进程中的结构

【Ucore操作系统】8. 并发

文章目录 【 0. 引言 】0.1 线程定义0.2 同步互斥 【 1. 内核态的线程管理 】1.1 线程概念1.2 线程模型与重要系统调用1.2.1 线程创建系统调用1.2.2 等待子线程系统调用1.2.3 进程相关的系统调用 1.3 应用程序示例1.3.1 系统调用封装1.3.2 多线程应用程序 – threads 1.4 线程管理的核心数据结构1.4.1 线程控制块1.4.2 包含线程的

Wireshark-Lab7:ICMP

更好的阅读体验 Lab7:ICMP In this lab, we’ll explore several aspects of the ICMP protocol: 在本实验中,我们将探讨 ICMP 协议的几个方面: ICMP messages generating by the Ping program; Ping 程序生成的 ICMP 消息; ICMP messages gener

ucore OS

初试ucore os,很感兴趣,争取一天学习一个lab

【uCore 操作系统】1. 应用程序与基本执行环境

文章目录 【 1. 代码框架简述 】1.1 OS 是怎么跑起来的?1.1.1 qemu 的作用1.1.2 rustsbi.bin 的作用 1.2 qemu 是怎么跑起来的?1.3 OS 文件夹1.3.1 kernel.ld1.3.2 entry.S1.3.3 main.c1.3.4 sbi.c 1.4 bootloader 文件夹 【 2. makefile 和 qemu 】2.1 make

ucore—17至20讲:同步互斥、信号量、死锁、进程通信

文章目录 第十七讲:同步互斥17.1 背景17.2 现实生活中的同步问题17.3 临界区及同步实现方式17.3.1 临界区17.3.2 禁用硬件中断实现同步17.3.3 基于软件的同步17.3.4 高级抽象的同步方法(锁) 第十八讲:信号量与管程18.1 信号量18.2 信号量的使用18.3 管程18.4 经典进程同步18.4.1 生产者-消费者问题18.4.2 读者-写者问题18.4.3

ucore—23讲:I/O系统

文章目录 第二十三讲:I/O子系统23.1 I/O特点23.1.1 设备接口类型23.1.2 同步和异步I/O 23.2 I/O结构(重要)23.3 I/O数据传输23.4 磁盘调度(类比处理机调度)23.5 磁盘缓存 第二十三讲:I/O子系统 23.1 I/O特点 23.1.1 设备接口类型 三种常见的设备 设备访问特征 在unix/linux中,所有IO设备都模型