您的当前位置:首页正文

操作系统实验报告,时钟原语

2020-12-06 来源:好走旅游网


一、实验名称

时钟原语的改进

二、实验目的

1. 理解并掌握Pintos的安装和使用;

2. 初步掌握Pintos内核线程构造及同步机理; 3. 具有对Pintos内核代码进行修改和调试的能力。

三、实验内容及要求

重新实现devices/timer.c中的timer_sleep()函数。该函数现有的实现虽然是正确的,但所采用的是“忙等”技术,通过不停地循环调用thread_yield()并查询是否已经达到等待时间。新的实现要求采用线程同步机制来替换这样的忙等技术。

void timer_sleep (int64_t ticks)的需求说明如下:

将调用此函数的线程挂起至少ticks所指定的若干个时钟周期。当这段时间过去后,将该线程激活并放入就绪队列。此函数可用于实现实时功能,如按照规定的时间间隔发送报文等。

Pintos系统时钟中断频率的缺省值为100,我们不建议修改此值,因为不适当的设置会造成很多意想不到的错误。

要求达到的指标:通过Pintos所提供的所有相关测试。

四、算法设计思想(字体标为红色的为改动的代码)

(一)忙等待VS.唤醒机制的实现:

/* 介绍实现中新声明的或者改变了的主要结构体、全局或局部变量,简短说明其设置的目的?*/

1.在thread.h文件中,我们在 struct thread 结构体中添加一个新的成员变量 ticks_blocked用来记录thread被阻塞了多久: struct thread {

/* Owned by thread.c. */

tid_t tid; /* 线程标识符 */

enum thread_status status; /* 线程状态 */

char name[16]; /* Name (for debugging purposes). */ uint8_t *stack; /* Saved stack pointer. */ int priority; /* 优先级 */

struct list_elem allelem; /* List element for all threads list. */ int ticks_blocked; /* 存储记录该进程已经被block多久了*/ /* Shared between thread.c and synch.c. */

struct list_elem elem; /* List element. */ #ifdef USERPROG /* Owned by userprog/process.c. */ uint32_t *pagedir; /* Page directory. */

#endif /* Owned by thread.c. */ unsigned magic; /* Detects stack overflow. */ };

2.打开thread.c,并修改thread_create函数,添加变量ticks_blocked,使得ticks_blocked初始化为0。注意添加的位置,需要在线程t创建出来之后,thread_unblock之前

intr_set_level (old_level); /*Initialize added vars*/ t->ticks_blocked = 0;

3.改动timer.c中的timer_sleep函数

Void

timer_sleep (int64_t ticks) /*让此线程等待ticks单位时长,然后再执行。参数是需要等待的时间长度*/

{

/* int64_t start = timer_ticks ();//记录开始时的系统时间 ASSERT (intr_get_level () == INTR_ON);//断言检测,中断应为开 while (timer_elapsed (start) < ticks) //如果流逝时间>=ticks时就返回。否则将持续占用cpu

thread_yield (); */

If(ticks<=0){

Return;// 检查用户程序中的等待时间是否有错; }

enum intr_level old_level=intr_disable(); //保存原先的中断状态 (thread_block函数调用需要中断关闭)!

struct thread * curThread = thread_current();

curThread->ticks_blocked = ticks;//线程应该阻塞(睡眠)的时间间隔

thread_block(); //阻塞进程

intr_set_level (old_level); //恢复原先的中断状态 }

4. thread_block函数的执行:

thread_block (void)

{

ASSERT (!intr_context ()); //检查调的函数符不符合条件,不能从原文中调 ASSERT (intr_get_level () == INTR_OFF); // 检查中断状态必须为关中断

thread_current ()->status = THREAD_BLOCKED; //线程阻塞态 schedule (); //调度程序schedule() }

5.修改timer.c中的timer_interrupt函数,使其每次中断都对所有线程执行block_check函数,用来检测

static void

timer_interrupt (struct intr_frame *args UNUSED)/*UNUSED是一个宏,表示这个参数没用, 每次时间中断时(即每一个时间单位(ticks)) 调用一次这个函数*/

{

ticks++;//计算机系统时钟

enum intr_level old_level=intr_disaable(); //保存原先的中断状态;关中断(稍后可返回中断关闭前的状态)

thread_foreach (checkInvoke,NULL);/*遍历当前TCB链表中所有线程,

对每个线程执行阻塞判断(是否为0),执行checkInvoke函数*/

intr_set_level (old_level); //恢复中断关闭前的状态

thread_tick ();//交给操作系统发出中断并且调度新的线程进驻cpu。 }

6.为thread.c文件中增加上面timer.c中的timer_interrupt函数中用到的函数checkInvoke函数,用来检查每个进程中的block_ticks是否为零 void

checkInvoke(struct thread *t, void *aux UNUSED) {

if (t->status == THREAD_BLOCKED&&t->ticks_blocked>0)/*判断线程是不是阻塞态*/ {

t-> ticks_blocked - -; //将等待的时间自减 if (t-> ticks_blocked = = 0) {

thread_unblock (t); //把t线程重新\"解锁\" } } }

7.在thread.h中对checkInvoke函数添加说明 添加一句:

Void checkInvoke(struct thread* t,void aux UNUSED);

(二)alarm-priority的实现

1.在thread .c中添加比较函数cmp,并在thread.h中添加相关说明 static bool

cmp(const struct list_elem *a,const struct list_elem *b,void *aux){ return (list_entry(a,struct thread,elem)->priority>

list_entry(b,struct thread,elem)->priority);

}

在thread.h中添加相关说明,添加一句:static bool cmp(const struct

list_elem *,const struct list_elem *,void *);

2.将thread.c中thread_unblock的list_push_back(&ready_list,&t->elem);改为:List_insert_ordered(&ready_list,&t->elem,cmp,NULL); void

thread_unblock (struct thread *t) {

enum intr_level old_level;

ASSERT (is_thread (t));

old_level = intr_disable ();

ASSERT (t->status == THREAD_BLOCKED); /*list_push_back (&ready_list, &t->elem);*/

list_insert_ordered (&ready_list, &t->elem,cmp,NULL); t->status = THREAD_READY; intr_set_level (old_level); }

/* Returns the name of the running thread. */

3. 对thread_yield函数和init_thread函数也做类似修改

void

thread_yield (void) {

struct thread *cur = thread_current (); enum intr_level old_level;

ASSERT (!intr_context ());

old_level = intr_disable (); if (cur != idle_thread)

/* list_push_back (&ready_list, &cur->elem);*/

list_insert_ordered (&ready_list, &cur->elem,cmp,NULL); cur->status = THREAD_READY; schedule ();

intr_set_level (old_level);

}

/* Invoke function 'func' on all threads, passing along 'aux'. This function must be called with interrupts off. */

static void

init_thread (struct thread *t, const char *name, int priority) {

ASSERT (t != NULL);

ASSERT (PRI_MIN <= priority && priority <= PRI_MAX); ASSERT (name != NULL);

memset (t, 0, sizeof *t); t->status = THREAD_BLOCKED;

strlcpy (t->name, name, sizeof t->name); t->stack = (uint8_t *) t + PGSIZE; t->priority = priority; t->magic = THREAD_MAGIC;

/* list_push_back (&all_list, &t->allelem);*/

list_insert_ordered (&all_list, &t->allelem,cmp,NULL); }

/* Allocates a SIZE-byte frame at the top of thread T's stack and returns a pointer to the frame's base. */

五、运行结果

因篇幅问题不能全部显示,请点此查看更多更全内容