重 庆 大 学
学 生 实 验 报 告
实验课程名称操作系统原理
开课实验室 重庆大学DS1501
学 院 软件工程 年级 2013 专业班
学 生 姓 名 学 号
开 课 时 间 2015 至 2016 学年第 一 学期
总 成 绩 教师签名
重庆大学软件学院制
洪明坚
《操作系统原理》实验报告
开课实验室:DS1501 2016 年1月 7 日 学院 软件学院 课程 名称 教师评语 ? 实验目的(软件需求文档) 年 月 日 年级、专业、班 实验项目 名 称 姓名 线程同步 成绩 指导教师 教师签名: 操作系统原理 掌握信号量的实现与应用 二、实验原理(软件设计文档) 互斥的实现 ? 一般不直接用sti/cli,而是用 – save_flags_cli(flags) 保存EFLAGS的值到一个变量flags中,然后IF=0 – restore_flags(flags) 把变量flags的值恢复到EFLAGS中 线程的睡眠和唤醒 ? 睡眠 – void sleep_on(struct wait_queue **head) ? ? 唤醒 – void wake_up(struct wait_queue **head, int n) ? 参数n表示要唤醒的线程个数 – n小于0表示唤醒该队列中的所有线程 ? sleep_on和wake_up必须在关中断环境中运行 – 用save_flags_cli/restore_flags保护 实现信号量 编辑文件epos/sem.c,实现如下四个函数 void *sys_sem_create(int value) value是信号量的初值 参数head是睡眠队列的头指针的指针
分配内存要用kmalloc,不能用malloc! 成功返回信号量句柄hsem,否则返回NULL int sys_sem_destroy(void *hsem) 释放内存要用kfree,不能用free! 成功返回0,否则返回-1 int sys_sem_wait(void *hsem) P操作,要用save_flags_cli/restore_flags和函数sleep_on 成功返回0,否则返回-1 int sys_sem_signal(void *hsem) V操作,要用save_flags_cli/restore_flags和函数wake_up 成功返回0,否则返回-1 把这四个函数做成系统调用,分别是sem_create/destroy/wait/signal 解决实验(二)中的花屏现象 在graphics.c中, 定义一个表示信号量的全局变量 static void *hsem = NULL; 分别在函数initGraphics和exitGraphics中创建和销毁信号量hsem 在函数setPixel中,用信号量hsem保护下面的临界区 switchBank(HIWORD(addr)); *p = getBValue(cr); *(p+1) = getGValue(cr); *(p+2) = getRValue(cr); 实现生产者/消费者 生产者生成随机数后,要画到缓冲区 消费者排序后,要清空缓冲区
三、使用仪器、材料(软硬件开发环境) Notepad++ expenv
四、实验步骤(实现的过程)
//定义信号量结构体 structsemaphore{ };
intvalue;
/*processes blocked by this semaphore*/ structwait_queue*wq_kbd;
sem.c:
void*sys_sem_create(intvalue) { }
intsys_sem_destroy(void*hsem) { }
intsys_sem_wait(void*hsem) { }
intsys_sem_signal(void*hsem) {
uint32_tflags;
save_flags_cli(flags);
((structsemaphore*)hsem)->value--;//P操作 if(((structsemaphore*)hsem)->value<0){ }
restore_flags(flags); return0;
sleep_on(&(((structsemaphore*)hsem)->wq_kbd)); kfree(hsem); return0;
if(hsem==NULL)
returnNULL;
elsereturn(structsemaphore*)hsem;//成功返回信号量句柄hsem structsemaphore*hsem; char*p;
p=(char*)kmalloc(sizeof(structsemaphore)); hsem=(structsemaphore*)p; hsem->value=value;//赋初值
hsem->wq_kbd=NULL;//!!!非常重要!!!
}
uint32_tflags;
save_flags_cli(flags);
((structsemaphore*)hsem)->value++;//V操作 if(((structsemaphore*)hsem)->value<=0){ }
restore_flags(flags); return0;
wake_up(&(((structsemaphore*)hsem)->wq_kbd),1);//等待队列中唤醒一个线程
把这四个函数做成系统调用 sem_create/destroy/wait/signal graphics.c中
//定义一个表示信号量的全局变量 staticvoid*hsem=NULL;
hsem=sem_create(1);//创建信号量 sem_destroy(hsem);//销毁信号量 以及
sem_wait(hsem);//用信号量hsem保护画点临界区 switchBank(HIWORD(addr)); *p=getBValue(cr); *(p+1)=getGValue(cr); *(p+2)=getRValue(cr);
sem_signal(hsem);
main.c: 声明信号量:
# definearrayNumber50 #defineN4//缓冲区数
staticvoid*mutex=NULL;//互斥信号量 staticvoid*full=NULL;//已生产产品数 staticvoid*empty=NULL;//空闲数 intstartposition=0;//生产者缓冲区坐标 staticintcount=0;//消费者缓冲区坐标 inttemp[4][50]={0}; intarray[N][arrayNumber];