进程的同步实验报告
进程(线程)同步和互斥实验报告

进程(线程)同步和互斥实验报告操作系统实验报告课程名称操作系统实验名称进程(线程)的同步与互斥成绩学生姓名作业君专业软件工程班级、学号同组者姓名无实验日期2021一、实验题目: : 进程(线程)的同步与互斥二、实验目的:自行编制模拟程序,通过形象化的状态显示,加深理解进程的概念、进程之间的状态转换及其所带来的 PCB 内容、组织的变化,理解进程与其 PCB 间的一一对应关系。
1.掌握基本的同步与互斥算法,理解生产者消费者模型。
2.学习使用 Windows 中基本的同步对象,掌握相关 API 的使用方法。
3.了解 Windows 中多线程的并发执行机制,实现进程的同步与互斥三、实验内容与要求:1.实验内容以生产者/消费者模型为依据,在 Windows 环境下创建一个控制台进程,在该进程中创建 n 个线程模拟生产者和消费者,实现进程(线程)的同步与互斥。
2.实验要求学习并理解生产者/消费者模型及其同步/互斥规则;学习了解 Windows 同步对象及其特性;熟悉实验环境,掌握相关 API 的使用方法;设计程序,实现生产者/消费者进程(线程)的同步与互斥;四、算法描述(含数据结构定义)或流程图#include <Windows.h> #include <iostream> #include<stdio.h> #include <math.h> #include <stdlib.h> #include <time.h> using namespace std;#define MA__THREAD_NUM 64//最大线程数 #define INTE_PER_SEC 1000//延迟时间的毫秒值 const int SIZE_OF_BUFFER = 10;//缓冲区长度 int ProductID = 0;//产品号 int ConsumeID = 0;//将被消耗的产品号 int in = 0;//产品进缓冲区时的缓冲区下标 int out = 0;//产品出缓冲区时的缓冲区下标 bool running = true;//判断程序能否继续执行的逻辑值 intg_buffer[SIZE_OF_BUFFER];//缓冲区是个循环队列 HANDLE g_hMute_;//公有信号量,用于线程间的互斥 HANDLEg_hFullSemaphore;//生产者的私有信号量,当缓冲区满时迫使生产者等待HANDLE g_hEmptySemaphore;//消费者的私有信号量,当缓冲区空时迫使消费者等待//定义一个结构体用于存储线程的信息 struct ThreadInfo {int serial;//线程号char entity;//线程类别(生产者或消费者)double delay;//等待时间double persist; //操作时间 };//生产者 void Producer(void_p) {//定义变量用于存储当前线程的信息DWORD m_delay;DWORD m_persist;int m_serial;//从参数中获得信息m_serial = ((ThreadInfo_)(p))->serial;m_delay = (DWORD)(((ThreadInfo_)(p))->delay _INTE_PER_SEC);m_persist = (DWORD)(((ThreadInfo_)(p))->persist _INTE_PER_SEC);while (running){//P 操作cout << “生产者线程” << m_serial << “ 请求生产.” << endl;WaitForSingleObject(g_hEmptySemaphore, INFINITE);cout << “生产者线程” << m_serial << “ 请求独占缓冲区.” << endl;WaitForSingleObject(g_hMute_, INFINITE);Sleep(m_delay);//延迟等待//生产一个产品cout << “生产者线程”<< m_serial << “ 生产” << ++ProductID << “ 号产品成功.” << endl;cout << “生产者线程” << m_serial << “ 请求将产品” << ProductID << “ 投入缓冲区.” << endl;//把新生产的产品放入缓冲区g_buffer[in] = ProductID;in = (in +1)%SIZE_OF_BUFFER;Sleep(m_persist);//操作等待cout << “生产者线程” << m_serial << “ 将产品” << ProductID << “ 投入缓冲区中成功.” << endl;//输出缓冲区当前的状态cout << “____________________________” << endl<< “\n 当前缓冲区情况如图(■代表已有产品,□代表没有产品):” << endl;for (int i = 0;i < SIZE_OF_BUFFER;++i){if (g_buffer[i] != 0)cout << “■”;elsecout << “□”;}cout << “\n\n____________________________\n” << endl;//V 操作ReleaseMute_(g_hMute_);ReleaseSemaphore(g_hFullSemaphore, 1, NULL);} }//消费者 void Consumer(void_p) {DWORD m_delay;DWORD m_persist;int m_serial;//从参数中获得信息m_serial = ((ThreadInfo_)(p))->serial;m_delay = (DWORD)(((ThreadInfo_)(p))->delay _INTE_PER_SEC);m_persist = (DWORD)(((ThreadInfo_)(p))->persist _INTE_PER_SEC);while (running){//P 操作cout << “消费者线程” << m_serial << “ 请求消费.” << endl;WaitForSingleObject(g_hFullSemaphore, INFINITE);cout << “消费者线程” << m_serial << “ 请求独占缓冲区.” << endl;WaitForSingleObject(g_hMute_,INFINITE);Sleep(m_delay); //延迟等待//从缓冲区中取出一个产品cout << “消费者线程” << m_serial << “ 请求取出一个产品.” << endl;ConsumeID = g_buffer[out];g_buffer[out] = 0;out = (out + 1) % SIZE_OF_BUFFER;cout << “消费者线程” << m_serial << “ 取出产品” << ConsumeID << “ 成功.” << endl;//消耗一个产品cout << “消费者线程” << m_serial << “ 开始消费消费产品” << ConsumeID << “.” << endl;Sleep(m_persist);cout << “消费者线程” << m_serial << “ 消费产品” << ConsumeID << “ 成功.” << endl;//输出缓冲区当前的状态cout << “____________________________” << endl<< “\n 当前缓冲区情况如图:” << endl;for (int i = 0;i < SIZE_OF_BUFFER;++i){if (g_buffer[i] != 0)cout << “■”;elsecout << “□”;}cout << “\n\n____________________________\n” << endl;//V 操作ReleaseMute_(g_hMute_);ReleaseSemaphore(g_hEmptySemaphore, 1, NULL);} }void prod_cons {//创建互斥信号量g_hMute_ = CreateMute_(NULL, FALSE, NULL);//创建同步信号量g_hEmptySemaphore = CreateSemaphore(NULL,SIZE_OF_BUFFER, SIZE_OF_BUFFER, NULL);g_hFullSemaphore = CreateSemaphore(NULL, 0,SIZE_OF_BUFFER, NULL);srand((unsigned)time(NULL));//以时间函数为种子const unsigned short THREADS_COUNT = rand % 5 + 5; //总的线程数(随机生成)//线程对象的数组HANDLE hThreads[MA__THREAD_NUM];ThreadInfo thread_info[MA__THREAD_NUM];DWORD thread_ID; //线程 IDint num = 0;//临时变量,用于循环语句cout << “系统开始模拟,并自动生成模拟数据...” << endl;system(“pause”); //暂停确认开始执行cout << “线程总数:” << THREADS_COUNT << endl;//循环随机生成各个线程的信息while (num != THREADS_COUNT){thread_info[num].serial = num + 1;if (rand % 2 == 1)thread_info[num].entity = "P";elsethread_info[num].entity = "C";thread_info[num].delay = rand % 5 + 1;thread_info[num].persist = rand % 6 + 2;num++;}cout << “\n 系统生成数据结束,模拟数据如下:” << endl<< “线程号线程类别延迟时间操作时间” << endl;for (int _ = 0;_ < THREADS_COUNT;_++)cout << “” << thread_info[_].serial << “\t”<< “” << thread_info[_].entity << “\t”<< “” << thread_info[_].delay << “\t\t”<< “” << thread_info[_].persist << endl;cout << “\n\n==================生产者-消费者开始==================\n” << endl;//创建线程for (int i = 0;i < THREADS_COUNT;i++){//创建生产者线程if (thread_info[i].entity == "P")hThreads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(Producer), ;thread_info[i], 0, ;thread_ID);//创建消费者线程elsehThreads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(Consumer), ;thread_info[i], 0, ;thread_ID);}while (running){if (getchar){//按回车后终止程序运行running = false;}}cout << “系统模拟结束...” << endl; } int main {cout << “\n==================生产者-消费者模拟==================\n” << endl;prod_cons; }五、实验过程1、记录生产者和消费者的同步执行过程。
操作系统 实验三 进程同步

集美大学计算机工程学院实验报告课程名称:操作系统指导教师:王丰实验成绩:实验编号:实验三实验名称:进程同步班级:计算12姓名:学号:上机实践日期:2015.5上机实践时间:2学时一、实验目的1、掌握用Linux信号灯集机制实现两个进程间的同步问题。
2、共享函数库的创建二、实验环境Ubuntu-VMware、Linux三、实验内容⏹需要的信号灯: System V信号灯实现☐用于控制司机是否可以启动车辆的的信号灯 S1=0☐用于控制售票员是否可以开门的信号灯 S2=0System V信号灯实现说明□ System V的信号灯机制属于信号灯集的形式, 一次可以申请多个信号灯.□同样利用ftok()生成一个key: semkey=ftok(path,45);□利用key申请一个包含有两个信号灯的信号灯集, 获得该集的idsemid=semget(semkey,2,IPC_CREAT | 0666);□定义一个联合的数据类型union semun{int val;struct semid_ds *buf;ushort *array;};□利用semctl()函数对信号灯初始化,参数有:信号灯集的id: semid要初始化的信号灯的编号:sn要设定的初始值:valvoid seminit(int semid, int val,int sn){union semun arg;arg.val=val;semctl(semid,sn,SETVAL,arg);}利用初始化函数,初始化信号灯:seminit(semid,0,0);//用来司机启动汽车的同步seminit(semid,0,1);//用来售票员开门的同步控制□利用semop()函数, 对信号灯实现V操作:sembuf是一个在头部文件中的预定义结构、semid—信号灯集id, sn—要操作的信号灯编号void semdown(int semid,int sn){/* define P operating*/struct sembuf op;op.sem_num=sn;op.sem_op=-1;//P操作为-1op.sem_flg=0;semop(semid,&op,1);}2、Linux的静态和共享函数库·Linux生成目标代码: gcc -c 源程序文件名(将生成一个与源程序同名的.o目标代码文件。
进程的同步与互斥实验报告

进程的同步与互斥实验报告1.实验目的进程(线程)的同步与互斥是操作系统中非常重要的概念,本实验旨在通过实际操作,加深对这些概念的理解和掌握。
通过编写多个进程(线程),并在其间进行同步与互斥操作,验证同步与互斥的实际效果。
2.实验环境本实验在Linux系统下进行,使用C/C++语言编程。
3.实验内容3.1同步在实验中,我们编写了两个进程A和B,这两个进程需要按照特定的顺序执行。
为了实现同步,我们使用信号量机制来确保进程A和B按照正确的顺序执行。
3.2互斥在实验中,我们编写了多个进程C和D,这些进程需要同时对一个共享资源进行访问。
为了实现互斥,我们使用互斥锁机制来确保同一时刻只有一个进程访问共享资源。
4.实验过程4.1同步实验编写进程A和进程B的代码,使用信号量机制实现同步。
进程A先运行,然后通过信号量唤醒进程B,进程B再开始执行。
通过观察进程的运行顺序,验证同步机制是否起作用。
4.2互斥实验编写进程C和进程D的代码,使用互斥锁机制实现互斥。
进程C和进程D同时对一个共享资源进行访问,通过互斥锁来确保同一时刻只有一个进程访问共享资源。
观察进程的输出结果,验证互斥机制是否起作用。
5.实验结果5.1同步实验结果进程A开始执行进程A执行完毕进程B开始执行进程B执行完毕5.2互斥实验结果进程C开始执行进程C访问共享资源进程C执行完毕进程D开始执行进程D访问共享资源进程D执行完毕6.实验分析通过上述结果可以看出,同步实验中进程A和进程B按照正确的顺序执行,证明了同步机制的有效性。
互斥实验中进程C和进程D能够正确地交替访问共享资源,证明了互斥机制的有效性。
7.实验总结通过本次实验,我深刻理解了进程(线程)的同步与互斥,并通过实际操作加深了对这些概念的理解。
同步和互斥是操作系统中非常重要的概念,对于应对资源竞争和提高程序性能具有重要意义。
在实际开发中,我们应该合理使用同步和互斥机制,以确保程序的正确性和并发执行的效率。
进程同步实验报告

一、实验目的1. 理解进程同步的概念和原理;2. 掌握进程同步的基本方法和机制;3. 学会使用信号量实现进程同步;4. 通过实验验证进程同步机制的有效性。
二、实验原理1. 进程同步:在多道程序设计中,进程的执行是并发的,但某些情况下需要保证多个进程按照一定的顺序执行,以避免出现数据不一致、死锁等问题。
进程同步是指通过某种机制,协调多个进程的执行顺序,保证它们能够正确、有效地共享资源。
2. 信号量:信号量是一种特殊的变量,用于实现进程同步。
信号量具有两个原子操作:P操作(wait)和V操作(signal)。
P操作用于申请资源,V操作用于释放资源。
3. 互斥锁:互斥锁是一种常见的进程同步机制,用于保证临界资源的互斥访问。
当一个进程进入临界区时,它会尝试获取互斥锁,如果锁已被其他进程获取,则该进程进入等待状态;当进程退出临界区时,它会释放互斥锁。
三、实验内容1. 实验环境:Linux操作系统,C语言编程环境。
2. 实验工具:gcc编译器、gdb调试器。
3. 实验步骤:(1)创建一个互斥锁,用于保护临界资源。
(2)编写两个进程,分别模拟对临界资源的访问。
(3)在进程访问临界资源前,使用P操作尝试获取互斥锁。
(4)在进程访问临界资源后,使用V操作释放互斥锁。
(5)编译并运行程序,观察进程执行情况。
四、实验结果与分析1. 实验结果:(1)在互斥锁的保护下,两个进程能够按照预期顺序访问临界资源。
(2)当其中一个进程正在访问临界资源时,另一个进程会进入等待状态。
(3)当进程访问临界资源完成后,它会释放互斥锁,允许其他进程访问。
2. 实验分析:(1)互斥锁能够有效地保护临界资源,避免数据不一致问题。
(2)信号量P操作和V操作保证了进程的同步,避免了死锁现象。
(3)通过实验验证了进程同步机制的有效性。
五、实验总结本次实验通过使用信号量和互斥锁,实现了进程同步。
实验结果表明,信号量和互斥锁能够有效地保证进程按照预期顺序执行,避免数据不一致和死锁等问题。
操作系统实验3进程同步报告

实验三进程同步一、实验目的:1.了解进程和线程的同步方法,学会运用进程和线程同步方法来解决实际问题;2.了解windows系统下Win32 API或Pthread信号量机制的使用方法;二、实验预备内容:1.对书上所说基于信号量的有限缓冲的生产者-消费者问题;2.对于信号量的概念有大概的了解,知道如何用信号量的wiat()和signal()函数如何取消应用程序进入临界区的忙等;三、实验环境说明:此实验在Win7(32位) CodeBlocks环境下实现,采用WinAPI的信号量机制。
四、实验内容:设计一个程序解决有限缓冲问题,其中的生产者与消费者进程如下图所示。
在Bounded-Buffer Problem(6.6.1节)中使用了三个信号量:empty (记录有多少空位)、full(记录有多少满位)以及mutex(二进制信号量或互斥信号量,以保护对缓冲区插入与删除的操作)。
对于本项目,empty和full将采用标准计数信号量,而mutex将采用二进制信号量。
生产者与消费者作为独立线程,在empty、full、mutex的同步前提下,对缓冲区进行插入与删除。
本项目可采用Pthread或Win32 API。
(本实验采用Win32 API)五、程序设计说明:1.全局变量:定义缓冲区数组及其环形队列表达方式,定义mutex、empty、full 三个信号量。
empty记录缓冲区有多少个空位;full记录缓冲区有多少个满位;mutex作为互斥信号量,保护对缓冲区插入或删除的操作。
具体定义如下:定义生产者、消费者线程结构和包含的信息:(由于题目中没有要求,因此只定义了编号一个变量)2.缓冲区:缓冲区是一个元数据类型为buffer_item(可通过typedef定义)的固定大小的数组,按环形队列处理。
buffer_item的定义及缓冲区大小可保存在头文件中:A.insert_item():先判断缓冲区是否已满,不满则向缓冲区中插入元素;B.remove_item()先判断缓冲区是否为空,不空则从缓冲区中删除元素;3.生产者线程:生产者线程交替执行如下两个阶段:睡眠一段随机事件,向缓冲中插入一个随机数。
进程同步实验报告

中北大学软件学院实验报告专 业: 软件工程方 向: 软件开发与测试课程名称: 操作系统班 级:学 号:姓 名:辅导教师:2017年9月制成绩:实验时间2017年11月5日8时至10时学时数22学时1.实验名称进程同步2.实验内容编程实现生产者-消费者问题的模拟。
3.基本要求1.生产者消费者对缓冲区进行互斥操作。
2. 缓冲区大小为10,缓冲区满则不允许生产者生产数据,缓冲区空则不允许消费者消费数据。
3. 生产者消费者各循环操作10次。
4. 实验原理或流程图生产者-消费者问题是一个经典的进程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制。
在同一个进程地址空间内执行的两个线程。
生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。
消费者线程从缓冲区中获得物品,然后释放缓冲区。
当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。
当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。
5.源程序#i n c l u d e<s t d i o.h>#i n c l u d e<p t h r e a d.h>#i n c l u d e<s e m a p h o r e.h>#i n c l u d e<u n i s t d.h>v o i d*p r o d u c t e r_f(v o i d*a r g);v o i d*c o n s u m e r_f(v o i d*a r g);s e m_t e m p t y;//信号量e m p t ys e m_t f u l l;//信号量f u l li n t r u n n i n g=1;i n t a p p l e_n u m=0;i n t m a i n(v o i d){p t h r e a d_t c o n s u m e r_t;//消费者p t h r e a d_t p r o d u c t e r_t;//生产者//p s h a r e d表示信号量共享类型, 为0时,表示只能在当前进程的//多个线程之间共享,不为0时,是可以和其他进程间共享该信号量//使用信号量,用来协作生产者和消费者的顺序,即实现同步效果s e m_i n i t(&e m p t y,0,1);//初始化e m p t y信号量s e m_i n i t(&f u l l,0,0);//初始化f u l l信号量p t h r e a d_c r e a t e(&c o n s u m e r_t,N U L L,c o n s u m e r_f,(v o i d*)&r u n n i n g); //创建消费者线程p t h r e a d_c r e a t e(&p r o d u c t e r_t,N U L L,p r o d u c t e r_f,(v o i d*)&r u n n i n g);//创建生产者线程//s l e e p(1);//睡眠3秒u s l e e p(1000);//睡眠10微秒r u n n i n g=0;p t h r e a d_j o i n(c o n s u m e r_t,N U L L);p t h r e a d_j o i n(p r o d u c t e r_t,N U L L);s e m_d e s t r o y(&e m p t y);s e m_d e s t r o y(&f u l l);r e t u r n0;}v o i d*p r o d u c t e r_f(v o i d*a r g){w h i l e(*(i n t*)a r g){s e m_w a i t(&e m p t y);a p p l e_n u m++;p r i n t f("p r o d u c t e r生产第%d个香蕉\n",a p p l e_n u m);s e m_p o s t(&f u l l);u s l e e p(1);}}v o i d*c o n s u m e r_f(v o i d*a r g){w h i l e(*(i n t*)a r g){s e m_w a i t(&f u l l);p r i n t f("c o n s u m e r消费第%d个香蕉\n",a p p l e_n u m);s e m_p o s t(&e m p t y);u s l e e p(1);}}6.运行截图7.实验心得本次实验学习了进程的同步问题,进程是计算机操作系统重要的一个功能,学好进程才能学好其他。
进程同步:实验报告

1.实验内容(进程的同步)(1)阅读理解示例程序。
(2)说明示例程序是否能适合解决N个生产者和1个消费者问题,并设计实验验证(3) 参照教材修改为N个生产者和1个消费者问题(4) 思考N个生产者和M个消费者问题的解决方案(不要求)(5) 利用信号量解决同步问题。
2.实验目的通过程序模拟及验证生产者消费者问题等经典问题,深入理解并发中的同步和互斥的概念3.实验原理(1)进程概念:(1.定义:程序的一次执行过程(2.三种基本状态:就绪状态,执行状态,阻塞状态(2)进程同步:(1.定义:并发进程在执行次序上的协调,以达到有效的资源共享和相互合作,使程序执行有可再现性。
(2.两种形式的制约关系:(一:资源共享关系:进程间接制约,需互斥地访问临界资源。
)、(二:相互合作关系:进程直接制约)(3.临界资源:一次仅允许一个进程访问的资源,引起不可再现性是因为临界资源没有互斥访问。
(3)信号量:定义一个用于表示资源数目的整型量S,它与一般的整型量不同,除初始化外,仅能通过两个标准的原子操作wait(S)和signal(S)来访问,俗称P,V操作。
通俗来讲就是用P来访问资源后减去一个单位资源,用V操作来释放一个单位资源就是现有资源上加一个单位资源。
4.实验内容一:说明示例程序是否能适合解决N个生产者和1个消费者问题,并设计实验验证答:示例程序不能解决多个生产者和消费者的问题,它是解决单个消费者和生产者的。
如果可以就要修改代码,如“二”所说。
二:多个消费者和生产者的问题如上图所示:如果要解决多个生产者和消费者的问题:第一步:分析上图得出了两种关系,分别是异步和同步的关系第二步:异步关系的是生产者和生产者之间的,因为同一时刻只能有一个生产者访问缓冲区,所以我们就可以设置临界资源.获得临界资源的生产者才能把产品放到缓冲区里第三步:同步关系有两个,首先是生产者和缓冲区之间,再是缓冲区和消费者之间。
他们都满足一前一后的关系,即当缓冲区空间未满时,生产者才可以放产品;缓冲区不为空的时候才可以让消费者取出产品消费。
进程的同步实验报告

操作系统实验报告哈尔滨工程大学计算机科学与技术学院进程的同步一.实验概述1.实验名称:进程的同步2.实验目的:1)使用EOS 的信号量,编程解决生产者—消费者问题,理解进程同步的意义;2)调试跟踪EOS 信号量的工作过程,理解进程同步的原理;3)修改EOS 的信号量算法,使之支持等待超时唤醒功能(有限等待),加深理解进程同步的原理。
3.实验类型:验证+设计4.实验内容:1)准备实验2)使用EOS 的信号量解决生产者-消费者问题3)调试EOS 信号量的工作过程4)修改EOS 的信号量算法二.实验环境操作系统:windows XP编译器:Tevalaton OS Lab语言:C三.实验过程1.设计思路和流程图2.实验过程1)准备实验,启动OS Lab,新建一个EOS Kernel项目和EOS应用程序,将EOS Kernel 项目中生成的SDK文件覆盖到ROS应用程序项目文件夹中的SDK文件夹;2)使用pc.c文件中的源代码,替换之前创建的EOS应用程序项目中EOSApp.c文件中的代码,并生成项目,启动调试,忽略调试的异常,立即激活虚拟机窗口中查看生产者-消费者同步执行的过程,结束此次调试;3)信号量结构体(SEMAPHORE)中的各个成员变量是由API 函数CreateSemaphore 的对应参数初始化的。
创建信号量,启动调试EOS应用程序,在OS Lab弹出的调试异常对话框中选择“是”,进入异常调试,在main函数中创建Empty信号量的代码行添加断点;EmptySemaphoreHandle = CreateSemaphore(BUFFER_SIZE, BUFFER_SIZE, NULL);4)启动调试,逐语句调试进入CreateSemaphore 函数。
可以看到此API 函数只是调用了EOS内核中的PsCreateSemaphoreObject 函数来创建信号量对象,继续逐语句调试试进入semaphore.c 文件中的PsCreateSemaphoreObject 函数。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
} io_cli(); *value=(*value)-1; io_sti(); } void semsignal(int *value){ io_cli(); *value=(*value)+1; io_sti(); } (6)实验结论 信号量是一种十分有效的解决临界区问题的方法,通过设定不允 许系统中断来有效保证了操作系统不会发生竞争条件,在进程进入临 界区后能阻止其他进程使用变量,在使用结束后能快速选择下一个进 入临界区的进程,信号量有效地解决了临界区难题。
(2)实验说明 原操作系统中并没有对进程的同步机制进行处理,这也就导致了 当系统出现竞争条件时,会导致程序运行结果的错误,本实验首先验 证了原程序不经改进可能会出现的竞争条件错误,然后使用了信号量 实现了生产者消费者问题,运用硬件关中断的方法实现了原子操作, 解决了临界区问题。 (3)实验操作 首先制定生产者消费者算法,启动函数,生产者进入生产,关闭 中断,生产产品,打开中断,进入消费者,关闭中断,消费产品,打 开中断,执行其他操作。 (4)具体实现 首先设置“仓库的大小”为 5,初始为空 进入生产后后,生产者向仓库中写入“Pd:no id”,意为生产出 第 id 号产品放入仓库。
(3)信号量和 TESTANDSET 有什么局限性 答:需要中断 cpu,通过软件的方式实现,必然会影响系统的效 率。 (4)为什么要对自旋锁进行优化 答:在进程等待过程中,进程在不断地等待接受可以执行的信号 ,这样大量的循环操作是的系统负担加重,适当的优化可以有效的提 高系统效率。 (5)内存分配算法优化如何验证 答:首先要看一下内存块的大小分别是多少事实上这里边只有两 个内存块,通过不断地分配内存,查看两种方式所能分配的内存多少 来衡量算法的性能。
们通过算法优化实现等待时间的缩短,提升操作系统的效率。 (2)改进措施
设置循环的睡眠时间,“等一会再敲门”。 睡眠时间可设置随检查次数而减少(aging)。 (3)具体实现 增加睡眠时间新系统模块:sleep_manager 与系统调用 void sleep(task,seconds)实现进程睡眠一定时间的功能。往与 process_ manager 共享的 buffer 中写入任务句柄、睡眠时间,执行睡眠函数, 让当前任务睡眠。循环检测睡眠缓冲区,如果有新的睡眠任务,把该 任务加入到睡眠列表中,并为之创建计时器,检测计时器,根据计时 器唤醒相应任务。
北京邮电大学实验报告
进程同步实验
学院: 计算机学院
科目: 操作系统实验
姓名: 陈星曼 孙博文 周鹏
张建南 何若愚 陈宇
组号:
3
一、实验概述 1. 实验名称 30 天自制操作系统 2. 实验目的 (1)阅读 30 天自制操作系统,理解操作系统的实现原理。 (2)理解操作系统中的竞争条件的产生和带来的问题。 (3)理解如何利用临界区来解决进程间的竞争条件。 (4)对操作系统有从底层向上的认识,再实现由表及里的深入
首先进入哲学家上厕所算法,首先哲学家进行思考,然后某哲学
家开始使用厕所,其他哲学家进入等待,哲学家使用完厕所后,释放
等待变量,其他哲学家开始抢占,选择一个哲学家进行上厕所,其他
进入等待。
(4)实验主要算法 基于 13 天 e 版本
void Toilet() {
while(testandset(lock)){ //the Philosopher is waiting
5
2.TEST&SET 解决哲学家上厕所问题 (1)实验说明
本实验实现了对哲学家上厕所问题的模拟,通过 TEST&SET 的方 法实现了哲学家等待以及抢占的过程,实验中通过对函数的不同传参 ,解决了确定哲学家身份的难题,并设定了验证代码来明显的显示哲 学家等待和抢占的效果。
(2)具体实现 哲学家:思考 3s,上厕所 2s(定时器) 厕所:需要有锁 上厕所动作:如果锁关闭(正在被占用)需要等待,否则占用并 锁门,使用完毕打开锁。 (3)实验操作
} //Philosopher uses toilet for a while Lock=false; }int TestAndSet(int *target) { io_cli(); int rv=*target; *target=1;// 1 means true; io_sti(); return rv; } (5)实验结论
(二)临界区问题:经典问题的解决临界区解决方 1.信号量解决生产者消费者问题 (1)实验流程图
3
准备实验 解决生产者-消费者问题
实现信号量
创建信 号量
等待释放 信号量
等待信号 量(不阻 塞)
释放信号 量(不唤 醒)
等待信号 释放信号 量(阻塞) 量(唤醒)
解决生产者消费者问题
结束实验
图 4-1.整体试验流程图
四. 实验中遇到的问题 (1)如何实现竞争条件 答:通过不断切换进程,增加每个进程内的执行操作数目,使多
次 count 操作发生重叠 (2)思考在信号量中为什么要使用原子操作? 答:在执行等待信号量和释放信号量的时候,是不允许 cpu 响应
外部中断的,如果此时 cpu 响应了外部中断,会产生不可预料的结 果,无法正常完成原子操作。
五.程序运行时的初值和运行结果 1.模拟竞争条件
9
2.生产者消费者问题 3.哲学家上厕所问题
4.内存优化验证: 初始情况
10
最先分配
最优分配
六.实验关键代码(源程序打包在附件中) 1.竞争条件模拟代码
void operate_plus(struct SHEET *sht_back,struct TASK* self) {
探索。 3. 实验类型 设计+验证+优化 4. 实验内容 (1)阅读 30 天自制操作系统,并选择合适版本进行实验。 (2)对原系统的进程同步机制予以修改,实现竞争条件,并通
过信号量解决生产者—消费者问题。 (3)通过 TEST&SET 算法实现哲学家上厕所问题,加深理解进程
同步的原理。 (4)对自旋锁算法进行优化,并对原系统的内存分配机制进行
for (;;) { io_cli(); if (fifo32_status(&fifo) == 0) { io_sti();
} else {
i = fifo32_get(&fifo);
io_sti();
if (i == 1) {
io_cli();
ready = 0;
io_sti();
while(ready == 0){
4
为了使显示效果更加明显,采用定时器的方式,使生产需要一定 时间,且生产之后休息很短时间。
(5)实验主要算法 基于 13 天 c 版本
void Producter() {
//produce items wait(empty); wait(mutex); //add to buffer signal(mutex); signal(full); } void Customer() { wait(full); wait(mutex); //remove an item signal(mutex); signal(empty); } void semwait(int *value){ for(;;){
(3)实验算法实现 void semwait(int *value){
for(;;){ if((*value)>0) break; sleep(thistask,sleeptime); sleeptime-=1;//或者不变
} io_cli(); *value=(*value)-1;
7
io_sti(); } (4)实验结论
(2)实验操作 由于模拟器环境下条件有限,为了构造这种情况我们需要很巧妙 的构造内存分配条件。首先分配比第一块内存最大大小大的内存 n 块,直到后一块无法分配再分配很小的内存块系统算法默认是选择最 先找到的,也就是前面一块但这时是后面一块更小,前一块更大,一 旦当分配完这些小的内存后,我们需要一个稍大的内存,本来如果不 把前面的内存分出去,我们的内存是可以分配的,但是前一块分配了 小内存后,产生了很多的内存碎片,这也就是让这一块内存无法分配 而我们的算法则可以最优分配,直到系统每一块都无法分配内存。
通过适当的 sleep 操作,aging 算法明显节约 cpu 等待时间,提 升了系统效率。对系统其它模块,如鼠标操作流畅度等都有了明显的 提升。
2.内存分配算法优化 (1)实验说明:原算法使用了最先选择算法,这种算法效率高,
运行速度快,但在某些情况下会产生很多的碎片,一旦碎片过多会导 致后续的内存无法分配,最终引起系统的异常,在此我们对最先算法 进行了修改,使用了最优的算法,为了区分这两种算法的区别,我们 设计实验来验证在不同情况下两种算法的区别。
优化,操作系统性能上的提高。
二、实验环境 WindowsXP(Windows7,8.1) + QEMU 模拟器
三、实验过程 (一)竞争条件的实现
1.问题的提出 临界区问题是嵌入式软件编程一个不得不面对的关键性问题。特 别对于底层驱动,代码在内存中只有一份,上层的多任务或者多进 程,都会对同一个驱动去访问,这样不可避免的遇到了任务之间打架 的问题,首先我们基于原操作系统实现竞争条件,通过大量的 count ++,count--操作增加碰撞几率。 2.实现算法: Proc 1: i++ for 100000 times Proc 2:
2
i-- for 100000 times 如果不出现错误结果应该是 0,如果结果非 0 则意味着出现错误。
3.如何观察 为了方便观察我们把++ 和 -- 的数目增加,通过把 i++对应指 令数目增加(i+i-i+i-i……),并通过设置优先级(减少时间片) 来实现更快速的进程切换,最后设置大量循环,多次模拟此过程(自 定义同步算法:ready=1 0 -1),以实现更容易观察竞争条件的目的 。 4.思路:原子操作的实现 算法:通过查找资料我们可以看到,临界区问题的解决算法有信 号量等,实现也有硬件和软件之分。 在当前的实验环境下,CPU 关中断可以使任务不会被抢,从而保 证操作的原子性;Test&Set 等特殊指令也可以实现,但是在当前指 令集中不存在。 上面的开关中断针对的是单 cpu,针对多 cpu 的解决方式比较复 杂,这里就不再展开。