实验四-同步与互斥-Linux实验报告

合集下载

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

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

进程(线程)同步和互斥实验报告操作系统实验报告课程名称操作系统实验名称进程(线程)的同步与互斥成绩学生姓名作业君专业软件工程班级、学号同组者姓名无实验日期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、记录生产者和消费者的同步执行过程。

进程的同步与互斥实验报告

进程的同步与互斥实验报告

进程的同步与互斥实验报告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.实验总结通过本次实验,我深刻理解了进程(线程)的同步与互斥,并通过实际操作加深了对这些概念的理解。

同步和互斥是操作系统中非常重要的概念,对于应对资源竞争和提高程序性能具有重要意义。

在实际开发中,我们应该合理使用同步和互斥机制,以确保程序的正确性和并发执行的效率。

操作系统实验报告——进程同步与互斥

操作系统实验报告——进程同步与互斥
if(Buffe‎r_Cri‎tical‎[i]==ProPo‎s){ TempP‎os = i;
break‎; } retur‎n TempP‎os; }
//生产者进程‎ void Produ‎ce(void *p) { //局部变量声‎ 明; DWORD‎ wait_‎for_s‎emaph‎ore,wait_‎for_m‎utex,m_del‎ay; int m_ser‎ial;
"semap‎hore_‎for_e‎mpty"); h_mut‎ex = Creat‎eMute‎x(NULL,FALSE‎,"mutex‎_for_‎updat‎e");
//下面这个循‎环用线程的‎ ID号来为‎相应生产线‎程的产品读‎ 写时所 //使用的同步‎信号量命名‎ ; for(j=0;j<(int)n_Thr‎ead;j++){
程,在该进程中‎ 创建 n 个线‎程模拟生产‎者和消费者‎ ,实现进程(线程)的同步与互
‎ 斥。
四、设计思路和‎ 流程框图
生产者进程‎的功能:生产东西,供消费者消‎费;消费者进程‎的功能:消费
生产者‎生产的东西‎。生产者生产‎产品并存入‎缓冲区供消‎费者取走使‎用,消费者
从缓‎冲器内取出‎产品去消费‎ 。在生产者和‎消费者同时‎工作时,必须禁止生‎产者将
retur‎n FALSE‎; }
//找出当前可‎以进行产品‎生产的空缓‎ 冲区位置; int FindP‎roduc‎ePosi‎tion() { int Empty‎Posit‎ion; for (int i =0;i<n_Buf‎fer_o‎r_Cri‎tical‎;i++)
if(Buffe‎r_Cri‎tical‎[i] == -1){ Empty‎Posit‎ion = i; //用下面这个‎特殊值表示‎本缓冲区正‎处于被写状‎ 态; Buffe‎r_Cri‎tical‎[i] = -2; break‎;

Linux操作系统实验实验报告

Linux操作系统实验实验报告

实验1:安装Linux系统【实验目的和要求】:安装Linux系统,掌握操作系统的系统配置,建立应用环境的过程。

【实验内容】:1、首先在windows系统中安装虚拟机。

在网上找到VMwareWorksttionPro版本,确定安装目录。

一直下一步,不需要太多的说明。

2、图为安装完成后的界面。

3、然后在阿里巴巴开源镜像网站下载centos系统镜像,然后虚拟机创建新的虚拟机,进行一些简单的虚拟机设置,设置了网络链接nat模式等等。

安装完成后的界面实验2:Linux下c语言开发【实验目的】:学会和掌握用c语言开发一个应用程序的全过程,包括,编译,调试等等。

【实验步骤】:首先在系统中查看是否已经安装有gcc,输入查看命令发现没有,于是需要安装gcc。

在centos系统中可以使用比较简便的yum命令。

在之前已经配置好了yum源。

直接输入yuminstallgcc。

回车自动安装程序和需要的依赖包。

因为虚拟机中和电脑很多地方切换使用不方便,所以安装了xshell软件。

图为xshell中的截图。

安装完毕。

然后使用vi或者vim编写hello.c运行,在屏幕上打印出hello,world。

实验3:进程创建【实验目的和要求】1.了解进程的概念及意义;2.了解子进程和父进程3.掌握创建进程的方法。

【实验内容】1.子进程和父进程的创建;2.编写附件中的程序实例【实验步骤】一1、打开终端,输入命令gedit1_fork.c,在1_fork.c文件中输入1_fork.bmp中的代码;2、输入命令gcc1_fork.c-o1_fork,回车后显示无错误;3、输入命令:./1_fork运行程序。

二、1、打开终端,输入命令gedit2_vfork.c,在2_vfork.c文件中输入2_vfork.bmp中的代码;2、输入命令gcc2_vfork.c-o2_vfork,回车后显示无错误:3、输入命令:./2_vfork运行程序。

从上面可以看到两次的运行结果不一样。

linux进程的管理互斥控制实验

linux进程的管理互斥控制实验
得分:
2、利用wait( )来控制进程执行顺序
代码:
结果:
父进程总是没有输出,不知道为什么。。。
评阅教师特殊评语:
评阅教师:
日期:
2)当启动新进程的时候,内核也给它们分配系统资源,如___CPU时间_____和___RAM空间_____。
3)永远不向父进程返回输出的进程叫做____僵进程__________。
4)由父进程派生出来的进程叫做______子进程____________进程。
5) _________父_______进程是一个派生另一个进程的进程。
思考
如何更新子进程内容?
答:调用exec( ),覆盖原有子进程。
(1)可执行文件加载时进行了哪些处理?
答:初始化,开辟内存,显示窗口是后期可选工作,并不是每一个程序都要窗口的每个程序,任何一个程序,任何一个可执行文件,启动运行时都要调用Ntdll.dll中的NtCreateProcess()。
(3)什么是进程同步?wait( )是如何实现进程同步的?
2.进程互斥实验
1)、进一步认识并发执行的实质
2)、通过分析实验结果,分析进程竞争资源的现象,学习解决进程互斥的方法
3.进程的控制实验
1)、掌握进程另外的创建方法:需认真分析实验结果,体会本次实验进程创建方法与fork的不同
2)、通过分析实验结果,熟悉进程的睡眠、同步、撤消等进程控制方法
实验内容及要求(详见实验讲义与实验指导书):
#include <stdio.h>
#include<unistd.h>
int main( )
{
int p1,p2;
while((p1=fork( ))= = -1);

实验四 Linux进程互斥

实验四 Linux进程互斥

实验四 Linux进程互斥一、实验目的熟悉Linux下信号量机制,能够使用信号量实现在并发进程间的互斥和同步。

二、实验题目使用共享存储区机制,使多个并发进程分别模拟生产者-消费者模式同步关系、临界资源的互斥访问关系,使用信号量机制实现相应的同步和互斥。

三、背景材料(一)需要用到的系统调用实验可能需要用到的主要系统调用和库函数在下面列出,详细的使用方法说明通过“man 2 系统调用名”或者“man 3 函数名”命令获取。

fork() 创建一个子进程,通过返回值区分是在父进程还是子进程中执行;wait() 等待子进程执行完成;shmget() 建立一个共享存储区;shmctl() 操纵一个共享存储区;s hmat() 把一个共享存储区附接到进程内存空间;shmdt() 把一个已经附接的共享存储区从进程内存空间断开;semget() 建立一个信号量集;semctl() 操纵一个信号量集,包括赋初值;semop() 对信号量集进行wait和signal操作;signal() 设置对信号的处理方式或处理过程。

(二)模拟生产者-消费者的示例程序本示例主要体现进程间的直接制约关系,由于使用共享存储区,也存在间接制约关系。

进程分为服务进程和客户进程,服务进程只有一个,作为消费者,在每次客户进程改变共享存储区内容时显示其数值。

各客户进程作为生产者,如果共享存储区内容已经显示(被消费),可以接收用户从键盘输入的整数,放在共享存储区。

编译后执行,第一个进程实例将作为服务进程,提示:ACT CONSUMER!!! To end, try Ctrl+C or use kill.服务进程一直循环执行,直到用户按Ctrl+C终止执行,或使用kill命令杀死服务进程。

其他进程实例作为客户进程,提示:Act as producer. To end, input 0 when prompted.客户进程一直循环执行,直到用户输入0。

(超详细)西电软院操作系统实验报告DOC

(超详细)西电软院操作系统实验报告DOC

(超详细)西电软院操作系统实验报告DOC操作系统课程设计实验报告册班级:1313012学号:...姓名:lan教师:杜军朝目录实验1 Linux(虚拟机)安装及Linux常用命令使用实验2 makefile的编写及Linux内核编译实验3 Linux的进程和线程实验4 同步与互斥实验5 文件系统重要提示:1.实验正文建议使用小四号或五号宋体。

2.若附加图形,则请直接嵌入到实验手册相应位置。

3.各实验的源程序,请按实验分目录存放,如第一个实验的源程序存放在目录lab1下,第二个实验的源程序存放在目录lab2下等等,依次类推。

4.可互相讨论,但严禁抄袭网络或同学的实验结果。

实验编号 1 题目Linux(虚拟机)安装及Linux常用命令使用实验目的1、掌握至少一种Linux系统的安装2、掌握虚拟机平台(Vmware Workstation)的使用和配置3、掌握至少一种配置Vmware中Linux系统与宿主机Windows 系统的文件交换的方法4、掌握常用的Linux命令5、了解Linux的帮助系统实验内容1、Linux(虚拟机)安装及Linux常用命令使用报告1、目录操作命令正文2、文件操作命令3、文本文件查看命令4、用户系统命令5、网络相关命令6、U盘的使用方法7、用户管理命令8、用户组账号管理9、文件权限设置10、设置文件属主和属组实验编号 2 题目makefile的编写及Linux内核编译实验目的1、掌握Linux中makefile文件的编写2、理解Linux内核的Makefile3、掌握至少一个版本Linux内核的编译步骤4、了解Linux内核的配置过程实验内容1、准备工作:相关软件的获取与安装(源代码,软件包)2、编译工作:配置,编译3、修改启动配置文件:修改grub2启动项4、能够正确的编译源代码5、能够用编译出的内核启动系统报告内容要求(1) 实现方法和思路(2) 测试及结果报告正文内核编译过程1、拷贝源代码到/usr/src目录下将文件添加共享文件夹中,然后在terminal输入以下命令:cd /mnt/hgfscp -r packages /usr/srccp linux-2.6.32.60 /usr/src2、在usr/src目录下解压源码:cd /usr/srctar xvf linux-2.6.32.60.tar.bz23、拷贝packages到“~”目录下:cd /usr/srccp -r packages ~4、安装软件包:dpkg –i *.deb5、转到内核源代码所在的目录“/usr/src/linux-2.6.32.60”:cd /usr/src/linux-2.6.32.606、输入make menuconfig,进入general setup选项,进入local version 菜单,添加版本标示:lan,保存并退出。

操作系统实验报告——进程同步与互斥

操作系统实验报告——进程同步与互斥

操作系统实验报告——进程同步与互斥一、实验内容本实验主要内容是通过编写程序来实现进程的同步与互斥。

具体来说,是通过使用信号量来实现不同进程之间的同步和互斥。

我们将编写两个进程,一个进程负责打印奇数,另一个进程负责打印偶数,两个进程交替打印,要求打印的数字从1开始,直到100结束。

二、实验原理进程的同步是指多个进程之间按照一定的顺序执行,进程之间互相等待的关系。

而进程的互斥是指多个进程竞争同一个资源,需要通过其中一种方式来避免同时访问共享资源,以免造成数据错乱。

在本实验中,我们使用信号量来实现进程的同步与互斥。

信号量是一个计数器,用于表示一些共享资源的可用数量。

进程在访问共享资源时,需要先对信号量进行操作,当信号量大于0时,表示资源可用,进程可以访问;当信号量等于0时,表示资源不可用,进程需要等待。

进程同步的实现可以通过信号量的P操作与V操作来完成。

P操作用于申请资源,当资源可用时,将计数器减一,并进入临界区;V操作用于释放资源,当资源使用完毕时,将计数器加一,使等待资源的进程能够申请。

进程互斥的实现可以通过信号量的P操作与V操作结合临界区来完成。

当多个进程需要访问共享资源时,需要先进行P操作,进入临界区,访问完毕后进行V操作,离开临界区。

三、实验步骤1.首先,我们需要创建两个进程,一个进程负责打印奇数,另一个进程负责打印偶数。

2. 然后,我们创建一个共享变量count,用来记录打印的数字。

3. 接着,我们创建两个信号量odd和even,用来控制进程的同步与互斥。

odd信号量初始值为1,表示打印奇数的进程可以访问;even信号量初始值为0,表示打印偶数的进程需要等待。

4.编写奇数打印进程的代码,首先进行P操作,判断奇数信号量是否大于0,如果大于0,表示可以打印奇数。

5. 如果可以打印奇数,将count加一,并输出当前的奇数,然后进行V操作,释放偶数打印进程的等待。

6.同样的,编写偶数打印进程的代码,首先进行P操作,判断偶数信号量是否大于0,如果大于0,表示可以打印偶数。

实验四同步与互斥Linux实验报告材料

实验四同步与互斥Linux实验报告材料

实验四同步与互斥Linux实验报告材料一、实验目的本次实验旨在深入理解和掌握Linux 操作系统中的同步与互斥机制。

通过实际的编程和操作,观察不同进程或线程之间的协作与竞争情况,从而更好地理解操作系统如何有效地管理资源和避免冲突。

二、实验环境本次实验使用的是 Linux 操作系统,具体版本为_____。

开发工具为_____,编译器为_____。

三、实验内容(一)信号量的使用信号量是一种用于实现进程或线程同步与互斥的重要机制。

在实验中,我们创建了一个简单的信号量示例,通过对信号量的操作来控制对共享资源的访问。

首先,定义了一个信号量,并初始化其值。

然后,创建了多个进程或线程,它们在访问共享资源之前需要先获取信号量,访问完成后释放信号量。

通过这种方式,确保了在同一时刻只有一个进程或线程能够访问共享资源,避免了数据的不一致性和冲突。

(二)互斥锁的应用互斥锁是另一种常见的同步机制,用于保证在任何时刻只有一个线程能够访问被保护的代码段或资源。

在实验中,我们创建了一个互斥锁,并在需要保护的关键代码段前加锁,执行完相关操作后解锁。

这样,即使多个线程同时尝试进入关键代码段,也只有一个线程能够成功获取锁,其他线程将被阻塞,直到持有锁的线程释放锁。

(三)条件变量的实践条件变量通常与互斥锁一起使用,用于实现线程之间的等待和通知机制。

我们创建了一个条件变量,并结合互斥锁实现了线程之间的通信。

当某个条件满足时,通过通知条件变量来唤醒等待的线程,使其继续执行后续操作。

四、实验步骤(一)准备工作1、安装所需的开发工具和编译器,并确保环境变量配置正确。

2、熟悉相关的 API 函数和库函数的使用方法。

(二)编写代码1、根据实验要求,分别编写使用信号量、互斥锁和条件变量的代码示例。

2、确保代码的逻辑清晰,注释完整,便于理解和调试。

(三)编译和运行1、使用编译器对编写的代码进行编译,检查是否存在语法错误。

2、运行编译后的程序,观察输出结果,分析程序的执行流程和同步效果。

操作系统实验-进程同步与互斥

操作系统实验-进程同步与互斥

操作系统实验-进程同步与互斥实验四:进程的管道通信实验题目进程的管道通信实验目的加深对进程概念的理解,明确进程和程序的区别。

学习进程创建的过程,进一步认识进程并发执行的实质。

分析进程争用资源的现象,学习解决进程互斥的方法。

学习解决进程同步的方法。

掌握Linux系统中进程间通过管道通信的具体实现实验内容使用系统调用pipe()建立一条管道,系统调用fork()分别创建两个子进程,它们分别向管道写一句话,如:Child process1 is sending a message!Child process2 is sending a message!父进程分别从管道读出来自两个子进程的信息,显示在屏幕上。

当然,仅仅通过屏幕上输出这两句话还不能说明实现了进程的管道通信,为了能够更好的证明和显示出进程的同步互斥和通信,在其中要加入必要的跟踪条件,如一定的输出语句等,来反映程序的并发执行情况实验要求这是一个设计型实验,要求自行、独立编制程序。

两个子进程要并发执行。

实现管道的互斥使用。

当一个子进程正在对管道进行写操作时,另一个欲写入管道的子进程必须等待。

使用系统调用lockf(fd[1],1,0)实现对管道的加锁操作,用lockf(fd[1],0,0)解除对管道的锁定。

实现父子进程的同步,当父进程试图从一空管道中读取数据时,便进入等待状态,直到子进程将数据写入管道返回后,才将其唤醒。

为了清楚的反应进程的同步,在子进程完成相应的操作后,调用sleep()函数睡眠一段时间(程序中定为3s)。

父进程先执行wait()函数,当有子进程执行完毕后,会得到子进程的返回结果并清理子进程。

若子进程没执行完,父进程一直执行wait()进行监听,知道有一个子进程执行完成为僵尸进程。

程序中用到的系统调用因为程序时在linux系统上进行编写的,所以其中要利用到相关的linux提供的系统调用。

所用到的系统调用包含在如下头文件中。

#include#include#include#include#include#includefork() 用于创一个子进程。

Linux多线程的互斥与同步控制及实践

Linux多线程的互斥与同步控制及实践
线程 # 二 是 通 过 设 置 私 用 信 号 量 及 : $2 原 语 操 作 来 实 现 " 流程为 %
:; %:<&*’=>!执行 !2<&*’A> :B7 :<&*’A>!执行 !2<&*’=> 其中 "&*’= 是线程 :; 的私用信号量 "&*’= 是线程 :B 的私用信号量 " 其初值根据具体资源情况而定 " 一般
线程间的互斥是为了避免对临界资源的同时使 用 " 从而避免因此而产生的不可预料的后果 ! 临界资源 是那些一次 只 能 被 一 个 线 程 使 用 的 资 源 " 在 计 算 机 系 统 中 有 很 多 软 硬 件 资 源 都 属 于 临 界 资 源 " 如 变 量 #堆 栈 # 链表 # 队列 # 打打印机等 ! 使用临界资源的那段代码 就称为临界 区 " 互 斥 就 是 两 个 或 两 个 以 上 的 共 用 同 一 资源的线程 不 能 同 时 进 入 该 资 源 的 临 界 区 " 它 可 以 保 证对资源操 作 的 正 确 性 和 完 整 性 ! 由 此 可 以 看 出 线 程 间的互斥关 系 是 由 于 对 共 有 资 源 的 竞 争 而 产 生 的 间 接 制约 " 线程之间并没有直接的联系 ! 实现线程间的互斥一般可通过两种途径实现 W 一 是 通 过 设 置 互 斥 锁 及 其 操 作 %加 锁 #解 锁 &来 实 现 " 流程为 X 图 %Y $
为一个正整数 " 一个为零 # &: 操作 "2 操作的判断分支 与在互斥中叙 述 的 一 致 ’ 私 用 信 号 量 只 能 由 其 拥 有 者 对其进行 : 操作 " 即线程只 能 由 自 己 将 自 己 阻 塞 " 而 不 能由对方阻塞 " 但两者可通过 2 操作彼此唤醒 #

实验四-同步与互斥-Linux实验报告

实验四-同步与互斥-Linux实验报告

实验四-同步与互斥-Linux实验报告实验四同步与互斥 Linux 实验报告一、实验目的本次实验旨在深入理解操作系统中进程的同步与互斥概念,通过在Linux 环境下进行编程实践,掌握相关的实现方法和技术,提高对并发控制的认识和应用能力。

二、实验环境操作系统:Linux(Ubuntu 2004)编程语言:C 语言开发工具:GCC 编译器三、实验原理(一)同步同步是指多个进程在执行过程中需要按照一定的顺序协调工作,以确保它们之间的操作具有正确的逻辑关系。

常见的同步机制包括信号量、条件变量等。

(二)互斥互斥是指在同一时刻,只允许一个进程访问共享资源,以避免多个进程同时操作导致的数据不一致或错误。

实现互斥的常见方法有互斥锁、临界区等。

四、实验内容(一)使用信号量实现生产者消费者问题1、问题描述生产者不断生产产品并放入缓冲区,消费者从缓冲区取出产品进行消费。

缓冲区大小有限,当缓冲区满时生产者停止生产,当缓冲区为空时消费者停止消费。

2、实现思路创建一个信号量来表示缓冲区的可用空间数量,另一个信号量表示缓冲区中已有的产品数量。

生产者在生产前检查可用空间信号量,消费者在消费前检查产品数量信号量。

3、代码实现```cinclude <stdioh>include <stdlibh>include <pthreadh>include <semaphoreh>define BUFFER_SIZE 5int bufferBUFFER_SIZE;int in = 0;int out = 0;sem_t empty_sem;sem_t full_sem;pthread_mutex_t mutex;void producer(void arg) {int item;while (1) {item = rand()% 100;sem_wait(&empty_sem);pthread_mutex_lock(&mutex);bufferin = item;printf("Producer: Produced item %d at position %d\n", item, in);in =(in + 1) % BUFFER_SIZE;pthread_mutex_unlock(&mutex);sem_post(&full_sem);}return NULL;}void consumer(void arg) {int item;while (1) {sem_wait(&full_sem);pthread_mutex_lock(&mutex);item = bufferout;printf("Consumer: Consumed item %d from position %d\n", item, out);out =(out + 1) % BUFFER_SIZE;pthread_mutex_unlock(&mutex);sem_post(&empty_sem);}return NULL;}int main(){pthread_t producer_thread, consumer_thread;sem_init(&empty_sem, 0, BUFFER_SIZE);sem_init(&full_sem, 0, 0);pthread_mutex_init(&mutex, NULL);pthread_create(&producer_thread, NULL, producer, NULL);pthread_create(&consumer_thread, NULL, consumer, NULL);pthread_join(producer_thread, NULL);pthread_join(consumer_thread, NULL);sem_destroy(&empty_sem);sem_destroy(&full_sem);pthread_mutex_destroy(&mutex);return 0;}```(二)使用互斥锁实现读者写者问题1、问题描述存在多个读者和一个写者,读者可以同时读取数据,但写者在写数据时不允许有其他读者或写者访问。

linux多线程实验报告

linux多线程实验报告

1 / 18实验八 Linux 多线程实验报告撰写人专业班级 学号姓名 完成时间。

一、 实验目的1、 了解什么是多线程,熟悉LINUX 的多线程机制;2、 掌握利用信号处理Linux 多线程的同步问题;3、掌握利用信号量处理Linux 多线程的互斥问题;4、 运用Linux 多线程的同步机制和互斥机制实现生产者消费者的编程。

二、 实验内容1. “生产者-消费者”问题如下:有一个有限缓冲区和两个线程:生产者和消费者。

他们分别不停地把产品放入缓冲区、从缓冲区中拿走产品。

一个生产者在缓冲区满的时候必须等待,一个消费者在缓冲区空的时候也必须等待。

另外,因为缓冲区是临界资源,所以生产者和消费者之间必须互斥执行。

它们之间的关系如图1所示。

现在要求使用共享内存来模拟有限缓冲区,并且使用信号量来解决“生产者-消费者”问题中的同步和互斥问题。

生产者和消费者问题描述2. 问题描述:假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。

吃东西的时候,他们就停止思考,思考的时候也停止吃东西。

餐桌中间有一大碗意大利面,每两个哲学家之间有一只餐叉。

因为用一只餐叉很难吃到意大利面,所以假设哲学家必须用两只餐叉吃东西。

他们只能使用自己左右手边的那两只餐叉。

请用Linux 线程编程解决。

2 哲学家进餐问题示意图三、实验过程与结果操作过程错误解决方法实验1 步骤一:编写producer_customer.c的文件在不同的编译器中for循环的用法不太一样,在这里最好不要使用for(inti=0;;)最好在外声明inti在for循环里直接写i=02/ 18步骤二:编译代码并且运行代码步骤三:运行完毕后,显示以下代码:生产者消费者先后生产数据以及取出数据,此程序中设置了两个消费者两个生产者,交替进行生产数据消费数据。

实验步骤一:编写philosopher.c的文件3/ 182步骤二:编译代码并且运行代码步骤三:4/ 18实验代码实验一:#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <time.h>#include <sys/ipc.h>#include <sys/shm.h>#include <sys/sem.h>#include <sys/types.h>#define MAX_BUFFER_SIZE 105/ 18#define SHM_MODE 0600#define SEM_MODE 0600#define SEM_FULL 0#define SEM_EMPTY 1#define MUTEX 2/*#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)// union semun is defined by including <sys/sem.h>#else// according to X/OPEN we have to define it ourselvesunion semun{int val;struct semid_ds *buf;unsigned short *array;};#endifunion semun su;//sem union,用于初始化信号量*/struct my_buffer{int head;int tail;char str[MAX_BUFFER_SIZE];int num; //缓冲区里字母数量int is_empty;};const int N_CONSUMER = 2;//消费者数量const int N_PRODUCER = 2;//生产者数量const int N_BUFFER = 10;//缓冲区容量6/ 18const int N_WORKTIME = 10;//工作次数int shm_id = -1;int sem_id = -1;pid_t child;pid_t parent;//得到10以内的一个随机数int get_random(){int digit;srand((unsigned)(getpid() + time(NULL)));digit = rand() % 10;return digit;}//得到A~Z的一个随机字母char getRandChar(){char letter;srand((unsigned)(getpid() + time(NULL)));letter = (char)((rand() % 26) + 'A');return letter;}//sem_id 表示信号量集合的 id//sem_num 表示要处理的信号量在信号量集合中的索引//P操作void waitSem(int sem_id,int sem_num){struct sembuf sb;sb.sem_num = sem_num;sb.sem_op = -1;//表示要把信号量减一7/ 18sb.sem_flg = SEM_UNDO;////第二个参数是 sembuf [] 类型的,表示数组//第三个参数表示第二个参数代表的数组的大小if(semop(sem_id,&sb,1) < 0){perror("waitSem failed");exit(1);}}//V操作void sigSem(int sem_id,int sem_num){struct sembuf sb;sb.sem_num = sem_num;sb.sem_op = 1;sb.sem_flg = SEM_UNDO;//第二个参数是 sembuf [] 类型的,表示数组//第三个参数表示第二个参数代表的数组的大小if(semop(sem_id,&sb,1) < 0){perror("sigSem failed");exit(1);}}//打印进程运行结果void printTime(){//打印时间time_t now;struct tm *timenow; //实例化tm结构指针time(&now);8/ 18timenow = localtime(&now);printf("执行时间: %s ",asctime(timenow));}int main(int argc, char ** argv){shm_id = shmget(IPC_PRIVATE,MAX_BUFFER_SIZE,SHM_MODE); //申请共享内存if(shm_id < 0){perror("create shared memory failed");exit(1);}struct my_buffer *shmptr;shmptr = shmat(shm_id, 0, 0); //将申请的共享内存附加到申请通信的进程空间if (shmptr == (void*)-1){perror("add buffer to using process space failed!\n");exit(1);}if((sem_id = semget(IPC_PRIVATE,3,SEM_MODE)) < 0){ //创建三个信号量,SEM_EMPTY,SEM_FULL和MUTEXperror("create semaphore failed! \n");exit(1);}if(semctl(sem_id,SEM_FULL,SETVAL,0) == -1){ //将索引为0的信号量设置为0-->SEM_FULLperror("sem set value error! \n");9/ 18exit(1);}if(semctl(sem_id,SEM_EMPTY,SETVAL,10) == -1){ //将索引为1的信号量设置为10-->SEM_EMPTYperror("sem set value error! \n");exit(1);}if(semctl(sem_id,MUTEX,SETVAL,1) == -1){ //将索引为3的信号量设置为1-->MUTEXperror("sem set value error! \n");exit(1);}shmptr -> head = 0;shmptr -> tail = 0;shmptr -> is_empty = 1;shmptr -> num = 0;int i;for(i = 0; i < N_PRODUCER; i++){parent = fork();if(parent < 0){perror("the fork failed");exit(1);}else if(parent == 0){shmptr = shmat(shm_id, 0, 0); //将申请的共享内存附加到申请通信的进程空间10/ 18if (shmptr == (void*)-1){perror("add buffer to using process space failed!\n");exit(1);}int count = 0;int j;for(j = 0; j < N_WORKTIME; j++){waitSem(sem_id, SEM_EMPTY);waitSem(sem_id, MUTEX);sleep(get_random());printf("-------------------------------------------------------------\n");printf("我是第 %d 个生产者进程,PID = %d\n", i + 1, getpid());/*生产产品*/char c = getRandChar(); //随机获取字母shmptr -> str[shmptr->tail] = c;shmptr -> tail = (shmptr->tail + 1) % MAX_BUFFER_SIZE;shmptr -> is_empty = 0; //写入新产品shmptr -> num++;/*打印输出结果*/printTime(); //程序运行时间int p;printf("缓冲区数据(%d个):",shmptr -> num); //打印缓冲区中的数据p = (shmptr->tail-1 >= shmptr->head) ? (shmptr->tail-1) :(shmptr->tail-1 + MAX_BUFFER_SIZE);11/ 18for (p; !(shmptr -> is_empty) && p >= shmptr -> head; p--){printf("%c", shmptr -> str[p % MAX_BUFFER_SIZE]);}printf("\t 生产者 %d 放入 '%c'. \n", i + 1, c);printf("-------------------------------------------------------------\n");fflush(stdout);sigSem(sem_id, MUTEX);sigSem(sem_id, SEM_FULL);}//将共享段与进程之间解除连接shmdt(shmptr);exit(0);}}for(i = 0; i < N_CONSUMER; i++){child = fork();if(child < 0)//调用fork失败{perror("the fork failed");exit(1);}else if(child == 0){int count = 0;shmptr = shmat(shm_id, 0, 0); //将申请的共享内存附加到申请通信的12/ 18进程空间if (shmptr == (void*)-1){perror("add buffer to using process space failed!\n");exit(1);}int j;for(j = 0; j < N_WORKTIME; j++){waitSem(sem_id, SEM_FULL);waitSem(sem_id, MUTEX);sleep(get_random());printf("-------------------------------------------------------------\n");printf("我是第 %d 个消费者进程,PID = %d\n", i + 1, getpid());/*消费数据*/char lt = shmptr -> str[shmptr -> head];shmptr -> head = (shmptr -> head + 1) % MAX_BUFFER_SIZE;shmptr -> is_empty = (shmptr->head == shmptr->tail); //shmptr -> num--;/*打印输出结果*/printTime(); //程序运行时间int p;printf("缓冲区数据(%d个):",shmptr -> num); //打印缓冲区中的数据p = (shmptr -> tail - 1 >= shmptr -> head) ? (shmptr -> tail-1) :(shmptr -> tail - 1 + MAX_BUFFER_SIZE);for (p; !(shmptr -> is_empty) && p >= shmptr -> head; p--)13/ 18{printf("%c", shmptr -> str[p % MAX_BUFFER_SIZE]);}printf("\t 消费者 %d 取出 '%c'. \n", i + 1, lt);printf("-------------------------------------------------------------\n");fflush(stdout);sigSem(sem_id,MUTEX);sigSem(sem_id,SEM_EMPTY);}//将共享段与进程之间解除连接shmdt(shmptr);exit(0);}}//主进程最后退出while (wait(0) != -1);//将共享段与进程之间解除连接shmdt(shmptr);//对共享内存区执行控制操作shmctl(shm_id,IPC_RMID,0);//当cmd为IPC_RMID时,删除该共享段shmctl(sem_id,IPC_RMID,0);printf("主进程运行结束!\n");fflush(stdout);exit(0);return 0;}14/ 18实验二:#include<sys/types.h>#include<unistd.h>#include<stdlib.h>#include<stdio.h>#include<pthread.h>#include<semaphore.h>#include<time.h>#define N 5 //哲学家数量#define LEFT(i) (i+N-1)%N //左手边哲学家编号#define RIGHT(i) (i+1)%N //右手边哲家编号#define HUNGRY 0 //饥饿#define THINKING 1 //思考#define EATING 2 //吃饭#define U_SECOND 1000000 //1秒对应的微秒数pthread_mutex_t mutex; //互斥量int state[N]; //记录每个哲学家状态//每个哲学家的思考时间,吃饭时间,思考开始时间,吃饭开始时间clock_t thinking_time[N], eating_time[N], start_eating_time[N],start_thinking_time[N];//线程函数void *thread_function(void *arg);int main(){15/ 18pthread_mutex_init(&mutex, NULL);pthread_t a,b,c,d,e;//为每一个哲学家开启一个线程,传递哲学家编号pthread_create(&a,NULL,thread_function,"0");pthread_create(&b,NULL,thread_function,"1");pthread_create(&c,NULL,thread_function,"2");pthread_create(&d,NULL,thread_function,"3");pthread_create(&e,NULL,thread_function,"4");//初始化随机数种子srand((unsigned int)(time(NULL)));while(1){;}}void *thread_function(void *arg){char *a = (char *)arg;int num = a[0] - '0'; //根据传递参数获取哲学家编号int rand_time;while(1){//关键代码加锁pthread_mutex_lock(&mutex);//如果该哲学家处于饥饿并且左右两位哲学家都没有在吃饭就拿起叉子吃饭if(state[num] == HUNGRY && state[LEFT(num)] != EATING &&16/ 18state[RIGHT(num)] != EATING){state[num] = EATING;start_eating_time[num] = clock(); //记录开始吃饭时间eating_time[num] = (rand() % 5 + 5) * U_SECOND; //随机生成吃饭时间//输出状态printf("state: %d %d %d %d %d\n",state[0],state[1],state[2],state[3],state[4]);//printf("%d is eating\n",num);}else if(state[num] == EATING){//吃饭时间已到,开始思考if(clock() - start_eating_time[num] >= eating_time[num]) //{state[num] = THINKING;//printf("%d is thinking\n",num);printf("state: %d %d %d %d %d\n",state[0],state[1],state[2],state[3],state[4]);start_thinking_time[num] = clock(); //记录开始思考时间thinking_time[num] = (rand() % 10 + 10) * U_SECOND; //随机生成思考时间}}else if(state[num] == THINKING){17/ 18//思考一定时间后,哲学家饿了,需要吃饭if(clock() - start_thinking_time[num] >= thinking_time[num]){state[num] = HUNGRY;printf("state: %d %d %d %d %d\n",state[0],state[1],state[2],state[3],state[4]);// printf("%d is hungry\n",num);}}pthread_mutex_unlock(&mutex);}}四、实验小结生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。

操作系统实训报告进程同步和互斥

操作系统实训报告进程同步和互斥

进程同步和互斥一、设计目的:通过实现哲学家进餐问题的同步深入了解和掌握进程同步和互斥的原理。

二、设计内容哲学家有N个,也定全体到达后开始讨论:在讨论的间隙哲学家进餐,每人进餐时都需使用刀、叉各一把,所有哲学家刀和叉都拿到后才能进餐。

哲学家的人数、餐桌上的布置自行设定,实现刀和叉的互斥使用算法的程序实现。

三、开发环境windows环境,VC6.0平台。

四、分析设计<一>实验原理不论是硬件临界资源,还是软件临界资源,多个进程必须互斥地对它进行访问。

每个进程中访问临界资源的那段代码称为临界区(Critical Section)。

每个进程中访问临界资源的那段程序称为临界区(Critical Section)(临界资源是一次仅允许一个进程使用的共享资源)。

每次只准许一个进程进入临界区,进入后不允许其他进程进入。

不论是硬件临界资源,还是软件临界资源,多个进程必须互斥地对它进行访问。

本程序主要使用了EnterCriticalSection (&cs)和LeaveCriticalSection (&cs)两个函数实现临界区互斥。

EnterCriticalSection (&cs)用来进入临界区,LeaveCriticalSection (&cs)用来离开临界区。

哲学家进餐问题设定图<二>程序结构1、主程序模块(详见图1)2、状态改变模块(详见图2)3、返回哲学家状态模块(详见图3)4、返回餐具状态模块(详见图4)<三>数据结构:程序中定义一个哲学家类,包含两个私有对象和四个公有对象。

Number对象:报讯哲学家的编号。

Status对象:用于保存当前该哲学家的状态,0表示正在等待(即处于饥饿状态)1表示得到餐具正在吃饭,2表示正在思考Philosopher(int num)方法:哲学家类构造函数,参数num表示哲学家编号find() const方法:返回该哲学家编号getinfo() const方法:返回哲学家当前状态Change()方法:根据题目要求改变哲学家的状态(等待->进餐->思考->等待…………)另外,程序中包含一个公有对象,bool类型数组tools[6],用来保存6把餐当前状态:true 表示该餐具当前空闲,false表示该餐具当前正被使用。

操作系统课程实验报告

操作系统课程实验报告

操作系统课程实验报告一、实验目的操作系统是计算机系统中最为关键的软件之一,它负责管理计算机的硬件资源和软件资源,为用户提供一个良好的工作环境。

通过操作系统课程实验,旨在深入理解操作系统的基本原理和功能,提高对操作系统的实际操作能力和问题解决能力。

二、实验环境本次实验使用的操作系统为Windows 10 和Linux(Ubuntu 1804),开发工具包括 Visual Studio Code、gcc 编译器等。

三、实验内容(一)进程管理1、进程创建与终止在 Windows 系统中,使用 C++语言创建多个进程,并通过进程句柄控制进程的终止。

在 Linux 系统中,使用 fork()系统调用创建子进程,并通过 exit()函数终止进程。

2、进程同步与互斥使用信号量实现进程之间的同步与互斥。

在 Windows 中,利用CreateSemaphore()和 WaitForSingleObject()等函数进行操作;在Linux 中,通过 sem_init()、sem_wait()和 sem_post()等函数实现。

(二)内存管理1、内存分配与释放在 Windows 中,使用 HeapAlloc()和 HeapFree()函数进行动态内存的分配与释放。

在 Linux 中,使用 malloc()和 free()函数完成相同的操作。

2、内存页面置换算法实现了几种常见的内存页面置换算法,如先进先出(FIFO)算法、最近最少使用(LRU)算法等,并比较它们的性能。

(三)文件系统管理1、文件创建与读写在 Windows 和 Linux 系统中,分别使用相应的 API 和系统调用创建文件,并进行读写操作。

2、目录操作实现了目录的创建、删除、遍历等功能。

四、实验步骤(一)进程管理实验1、进程创建与终止(1)在 Windows 系统中,编写 C++程序,使用 CreateProcess()函数创建新进程,并通过 TerminateProcess()函数终止指定进程。

操作系统linux版实验报告

操作系统linux版实验报告

操作系统实验报告(Linux版)网络142 潘豹 142999实验一观察Linux进程状态一、实验目得在本实验中学习Linux操作系统得进程状态,并通过编写一些简单代码来观察各种情况下,Linux进程得状态,进一步理解进程得状态及其转换机制。

二、实验环境硬件环境:计算机一台,局域网环境;软件环境:Linux Ubuntu操作系统,gcc编译器。

(四)查瞧“不可中断阻塞”状态(D)创建一个C程序,如uninter_status、c,让其睡眠30s代码:#include<unistd、h〉#include<stdio、h〉int main(){int i=0,j=0,k=0;for(i=0;i<1000000;i++){for(j=0;j<1000000;j++){k++;k--;}}}实验结果:(二)查瞧“暂停”状态(T)运行run_status进程,其进入R状态:代码同上:(三)查瞧“可中断阻塞”状态(S)创建一个C程序,如interruptiblie_status、c,让其睡眠30s编译链接,后台运行该程序(后接&符号),并使用ps命令查瞧运行状态代码:#include〈unistd、h>#include<stdio、h>int main(){sleep(30);return;}实验结果:(四)查瞧“不可中断阻塞”状态(D)创建一个C程序,如uninter_status、c,让其睡眠30s编译链接,后台运行该程序(后接&),并使用ps命令查瞧运行状态代码:#include〈unistd、h>#include〈stdio、h>intmain(){if(vfork()==0){sleep(300);return;}}实验结果:(五)查瞧“僵尸”进程(Z)创建一个C程序,如zombie_status、c,在其中创建一个子进程,并让子进程迅速结束,而父进程陷入阻塞编译链接,后台运行该程序(后接&),并使用ps命令查瞧运行状态(30s内)代码:#include<unistd、h>#incldue<stdio、h>int main(){if(fork()){sleep(300);}}实验结果:实验二观察Linux进程/线程得异步并发执行一、实验目得通过本实验学习如何创建Linux进程及线程,通过实验,观察Linux进程及线程得异步执行。

操作系统-管理Linux系统进程-进程互斥实验-进程的控制实验-实验0304

操作系统-管理Linux系统进程-进程互斥实验-进程的控制实验-实验0304
步骤6:试调试下二段代码。并写明结果(考虑fork与sleep是什么函数)
1、
int main()
{
int p1,i;
while ((p1=fork())==-1);
if (p1>0)
for (i=0;i<5;i++)
{
printf("I am parent.\n");
sleep(1);
}
else
for (i=0;i<5;i++)
僵进程:子进程没有带着输出返回给父进程。这样的进程在系统中变成丢失的进程。
使用此前的信息,完成以下填空:
1) Linux系统中,几乎每一个启动的进程,都会由内核分配一个唯一的PID进程标识符,用于跟踪从进程启动到进程结束。
2)当启动新进程的时候,内核也给它们分配系统资源,如内存空间和CPU资源。
3)永远不向父进程返回输出的进程叫做____。
4)由父进程派生出来的进程叫做_____。
5) _____进程是一个派生另一个进程的进程。
6)运行用于提供服务的Linux系统进程是____。
7)如果父进程在子进程之前结束,它创建了一个_____进程。
步骤4:回顾ps命令和信息。
ps命令用于列出当前系统中运行的进程。
如果一个进程耗时太长,或者看上去好像已经终止了,表现为一个终端窗口不再响应或挂起,通常需要使用ps查看系统中的进程。通过列出进程,可以查看初始化进程的命令或程序的名字,以及所有它派生出来的子进程。通过多次执行ps命令,查看进程的时间——进程占用的CPU时间,可以检查一个进程是否还在运行。如果时间不再增长,那么进程可能已经终止了。如果进程占用太长的时间或者已经停止,可以使用ps命令检查进程的进程ID (PID),然后杀死进程。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验四同步与互斥【实验目的和要求】1、掌握进程(线程)的同步与互斥。

2、掌握生产者消费者问题的实现方法。

3、掌握多线程编程方法。

【实验内容】实现生产者消费者问题1、有一个仓库,生产者负责生产产品,并放入仓库,消费者会从仓库中拿走产品(消费)。

2、仓库中每次只能入一个(生产者或消费者)。

3、仓库中可存放产品的数量最多10个,当仓库放满时,生产者不能再放入产品。

4、当仓库空时,消费者不能从中取出产品。

5、生产、消费速度不同。

【实验原理】1、信号量mutex提供对缓冲池访问的互斥要求并初始化为1,信号量empty和full分别用来表示空缓冲项和满缓冲项的个数,信号量empty初始化为n,信号量full初始化为0。

2、定义如下结构及数据:定义缓冲区内的数据类型:typedef int buffer_item;缓冲区:buffer_item buffer[BUFFER_SIZE];对缓冲区操作的变量:int in,out;信号量mutex提供了对缓冲池访问的互斥要求:pthread_mutex_t mutex;信号量empty和full分别表示空缓冲顶和满缓冲顶的个数:sem_t empty,full;可以设定生产者的生产速度及消费者的消费速度:int pro_speed,con_speed; 对缓冲区操作的自增函数:#define inc(k)if(k<BUFFER_SIZE)k=k+1;else k=03、并定义了如下实现问题的函数模块:将生产的产品放入缓冲区:int insert_item(buffer_item item)从缓冲区内移走一个产品:int remove_item(buffer_item*item)生产者进程:void*producer(void*param)消费者进程:void*consumer(void*param)生产者结构进程消费者结构进程【程序代码】//sx.c#include<stdio.h>#include<stdlib.h>#include<pthread.h>#include<semaphore.h>#include<time.h>#define inc(k) if(k<BUFFER_SIZE) k=k+1;else k=0#define BUFFER_SIZE 10//缓冲区的大小typedef int buffer_item;//定义缓冲区内的数据类型buffer_item buffer[BUFFER_SIZE];//缓冲区int in,out;//对缓冲区操作的变量pthread_mutex_t mutex;//信号量mutex提供了对缓冲池访问的互斥要求sem_t empty,full;//信号量empty和full分别表示空缓冲顶和满缓冲顶的个数int pro_speed,con_speed;//可以设定生产者的生产速度及消费者的消费速度int insert_item(buffer_item item){//将生产的产品放入缓冲区buffer[in]=item;printf("******insert缓冲池第%d号******\n",in);inc(in);}int remove_item(buffer_item *item){//从缓冲区内移走一个产品*item = buffer[out];printf("******remove缓冲池第%d号******\n",out);inc(out);}void *producer(void *param){//生产者进程buffer_item item;int num = 0;while(1){sleep(rand()%(16-pro_speed));printf("\n******第%d次生产******\n",++num);printf("******等待empty信号******\n");sem_wait(&empty);printf("******等待解锁******\n");pthread_mutex_lock(&mutex);printf("******上锁,准备生产******\n");item = rand()%1000+1;printf("******生产产品%d*******\n",item);insert_item(item);printf("*******解锁******\n");printf("******第%d次生产结束*******\n\n",num); pthread_mutex_unlock(&mutex);sem_post(&full);}}void *consumer(void *param){//消费者进程buffer_item item;int num = 0;while(1){sleep(rand()%(16-con_speed));printf("\n******第%d次消费*****\n",++num); printf("******等待full信号******\n");sem_wait(&full);printf("******等待解锁******\n");pthread_mutex_lock(&mutex);printf("******上锁,准备消费******\n");remove_item(&item);pthread_mutex_unlock(&mutex);sem_post(&empty);printf("******消费产品%d*******\n",item);printf("*******解锁******\n");printf("******第%d次消费结束*******\n\n",num); }}int main()//主函数{pthread_t tid1,tid2;pthread_attr_t attr1,attr2;srand(time(NULL));pthread_mutex_init(&mutex,NULL);//初始化sem_init(&empty,0,BUFFER_SIZE);sem_init(&full,0,0);in=0;out=0;printf("***********************\n");printf("********开始!***********\n");printf("***********************\n");printf("生产者速度(1-15):\n");scanf("%d",&pro_speed);printf("消费者速度(1-15):\n");scanf("%d",&con_speed);pthread_attr_init(&attr1);pthread_create(&tid1,&attr1,producer,NULL);pthread_attr_init(&attr2);pthread_create(&tid2,&attr2,consumer,NULL);sleep(100);printf("*******程序over*******\n");return 0;}【实验步骤】编写程序代码gedit sx.c,再对代码进行编译gcc sx.c –o sx –lpthread,编译无错误,进行运行./sx,根据提示要求进行填写生产者和消费速度,观察消费者和生产者进程。

【实验结果】【实验体会】 1、Linux 中生成线程方法:第一种方式是用pthread 库来实现的,是在用户程序本身中实现线程,这实际上是对线程的一种模拟,线程之间的切换和调度是在用户的进程内部进行的,这种方式就被称为用户空间的线程。

这种线程的好处是实现非常简单,性能也非常好,因为线程之间的切换都在用户进程内部进行,切换开销比较小。

缺点也非常明显,首先就是不能充分利用高端系统的SMP 多处理器的优点,因为一个进程只能由一个处理器处理,第二点由于用户空间是在用户空间切换,某个线程遇到一个需要阻塞的系统调用进而就会造成这个进程被阻塞,因而所有线程被阻塞。

第二种方式是通过修改进程的实现方式来完成,可以使用不完全的进程创建方式创建共享数据空间的进程,在Linux 下这种系统调用为clone()。

2、Ptrtead 生成线程: POSIX thread 简称为pthread ,Posix 线程是POSIX 标准线程该标准定义内部API 创建和操纵线程。

数据类型pthread_t:线程句柄pthread_attr_t:线程属性线程操纵函数(省略参数):pthread_create():创建一个线程pthread_exit():终止当前线程pthread_cancel():中断另外一个线程的运行pthread_join():阻塞当前的线程,直到另外一个线程运行结束pthread_attr_init():初始化线程的属性pthread_attr_setdetachstate():设置脱离状态的属性(决定这个线程在终止时是否可以被结合)pthread_attr_getdetachstate():获取脱离状态的属性pthread_attr_destroy():删除线程的属性pthread_kill():向线程发送一个信号______________________________________________________________________________________________________________Welcome To Download !!!欢迎您的下载,资料仅供参考!精品资料。

相关文档
最新文档