pintos操作系统实验Project1-时钟

Posted puyalee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了pintos操作系统实验Project1-时钟相关的知识,希望对你有一定的参考价值。

目前在学习操作系统,在这里用于记录学习过程,学习过程中主要参考了laiy的文章,作为一个初学者,有些地方理解不是很透彻,就当作是笔记了。

Project1的实验内容是重新设计timer_sleep函数,使用指定方法优化其实现方式。

pintos里面原始的timer_sleep函数是这样的,这里的实现方式是使用忙等。

1 void
2 timer_sleep (int64_t ticks) 
3 {
4   int64_t start = timer_ticks ();                    //获取当前时钟
5 
6   ASSERT (intr_get_level () == INTR_ON);        //确认当前状态是开中断
7   while (timer_elapsed (start) < ticks)         //当调用之后过去的时间还没到睡眠时间时
8     thread_yield ();                    //是当前进程进入就绪队列等待,调用新的进程
9 }

这种方法实现起来较为简单,但是也有明显的缺陷,那就是在睡眠时间里进程仍然在占用着CPU资源。我们的任务就是要解决这个问题,方案是利用阻塞机制,当用户程序调用timer_sleep时,使当前进程进入阻塞状态,并调用其它进程,当睡眠时间结束时唤醒该进程。

到这里应该思考几个问题:

  1. 用什么来记录用户调用时传递的睡眠时间?
  2. 在哪里对睡眠时间进行什么操作?
  3. 如何检测睡眠时间是否结束?

经过教员讲解,加之学习laiy的文章,基本理出一条思路:修改timer_sleep函数,使得睡眠时间大于0的时候将进程变为阻塞状态,为了实现这一点,需要创建一个变量sleep_ticks传递睡眠时间,在创建进程的时候初始化为0,当调用timer_sleep后传参;而后在每个时钟中断均需要对每个进程进行检测sleep_ticks是否大于0,每检测一次sleep_ticks--,直至sleep_ticks=0时唤醒该进程

下面进行具体实现:

首先在线程的结构体中加入我们需要的成员

1 int64_t sleep_ticks;                                 /* # of timer ticks since blocked. */

  在创建线程时初始化sleep_ticks

1 t->sleep_ticks = 0;

重写timer_sleep函数

 1 /* modified func */
 2 void
 3 timer_sleep (int64_t ticks)
 4 {
 5   if(ticks <= 0)                                            //如果用户调用的睡眠时间<=0,则不阻塞该线程
 6         return;
 7 
 8   ASSERT (intr_get_level () == INTR_ON);                  //确认中断是打开的
 9   enum intr_level old_level = intr_disable ();             //关中断,并保存之前的中断状态,即lod_level是开中断状态
10   struct thread *current_thread = thread_current ();       //获取当前线程信息的结构体指针
11   current_thread->sleep_ticks = ticks;                     //将用户需要线程睡眠的时间参数传给sleep_ticks
12   thread_block ();                                         //将当前线程状态设置为阻塞态
13   intr_set_level (old_level);                              //开中断
14 }

 利用每一个时钟中断对每个线程进行检测,需要在timer_interrupt中加入函数thread_foreach()

1 thread_foreach (blocked_thread_check, NULL);                        //对每个线程都应用函数blocked_thread_check

 这里的blocked_thread_check即负责检测每个线程的sleep_ticks,如果减到0则唤醒该进程,需写入thread.c里面

 1 /* Check the blocked thread */
 2 void
 3 blocked_thread_check (struct thread *t,void *aux UNUSED)
 4 {
 5   if (t->status == THREAD_BLOCKED && t->sleep_ticks > 0)               //对于处于阻塞状态的线程才会检测其sleep_ticks
 6   {
 7       t->sleep_ticks--;                                                //检测其sleep_ticks值减1是否为0,等于0则表示
 8       if (t->sleep_ticks == 0)                                         //在这个时钟结束时应该被unblock
 9       {
10           thread_unblock(t);                              //唤醒该进程  
11       }
12   }
13 }

 blocked_thread_check需要在thread.h里面声明

1 /* check the block state */
2 void blocked_thread_check (struct thread *t,void *aux UNUSED);

 至此Project1就完成了,测试结果也在意料之中

 

以上是关于pintos操作系统实验Project1-时钟的主要内容,如果未能解决你的问题,请参考以下文章

Pintos Project1的同步问题

Pintos Project 2

获取信号量必须是原子的。 Pintos 的 sema_down 安全吗?

Linux基于 Pintos 实现新的用户级程序的系统调用 | 冯诺依曼架构

看表情包学Linux冯诺依曼架构 | 理解操作系统 | 基于 Pintos 实现新的用户级程序的系统调用

看表情包学Linux冯诺依曼架构 | 理解操作系统 | 基于 Pintos 实现新的用户级程序的系统调用