实验四 同步与互斥 Linux实验报告
实验、进程的同步与互斥——生产者消费者

实验、进程的同步与互斥——⽣产者消费者1. 1. 实验⽬的两个或两个以上的进程,不能同时进⼊关于同⼀组共享变量的临界区域,否则可能发⽣与时间有关的错误,这种现象被称作进程互斥。
对CPU的速度和数⽬不做出任何假设的前提下,并发进程互斥访问临界资源,是⼀个较好的解决⽅案。
另外,还需要解决异步环境下的进程同步问题。
所谓异步环境是指:相互合作的⼀组并发进程,其中每⼀个进程都以各⾃独⽴的、不可预知的速度向前推进;但它们⼜需要密切合作,以实现⼀个共同的任务,即彼此“知道”相互的存在和作⽤。
实验⽬的:分析进程争⽤资源的现象,学习解决进程同步与互斥的⽅法。
本实验属于设计型实验,实验者可根据⾃⾝情况选⽤合适的开发环境和程序架构。
1. 2. 实验原理信号量的PV操作与处理相关,P表⽰通过的意思,V表⽰释放的意思。
1962年,狄克斯特拉离开数学中⼼进⼊位于荷兰南部的艾恩德霍芬技术⼤学(Eindhoven Technical University)任数学教授。
在这⾥,他参加了X8计算机的开发,设计与实现了具有多道程序运⾏能⼒的操作系统——THE Multiprogramming System。
THE是艾恩德霍芬技术⼤学的荷兰⽂Tchnische Hoogeschool Eindhov –en的词头缩写。
狄克斯特拉在THE这个系统中所提出的⼀系统⽅法和技术奠定了计算机现代操作系统的基础,尤其是关于多层体系结构,顺序进程之间的同步和互斥机制这样⼀些重要的思想和概念都是狄克斯特拉在THE中⾸先提出并为以后的操作系统如UNIX等所采⽤的。
为了在单处理机的情况下确定进程(process)能否占有处理机,狄克斯特拉将每个进程分为“就绪”(ready)、“运⾏”(running)和“阻塞”(blocking)三个⼯作状态。
由于在任⼀时刻最多只有⼀个进程可以使⽤处理机,正占⽤着处理机的进程称为“运⾏”进程。
当某进程已具备了使⽤处理机的条件,⽽当前⼜没有处理机供其使⽤,则使该进程处于“就绪”状态。
进程的同步与互斥实验报告

进程的同步与互斥实验报告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.实验总结通过本次实验,我深刻理解了进程(线程)的同步与互斥,并通过实际操作加深了对这些概念的理解。
同步和互斥是操作系统中非常重要的概念,对于应对资源竞争和提高程序性能具有重要意义。
在实际开发中,我们应该合理使用同步和互斥机制,以确保程序的正确性和并发执行的效率。
操作系统实验报告——进程同步与互斥

break; } return TempPos; }
//生产者进程 void Produce(void *p) { //局部变量声 明; DWORD wait_for_semaphore,wait_for_mutex,m_delay; int m_serial;
"semaphore_for_empty"); h_mutex = CreateMutex(NULL,FALSE,"mutex_for_update");
//下面这个循环用线程的 ID号来为相应生产线程的产品读 写时所 //使用的同步信号量命名 ; for(j=0;j<(int)n_Thread;j++){
程,在该进程中 创建 n 个线程模拟生产者和消费者 ,实现进程(线程)的同步与互
斥。
四、设计思路和 流程框图
生产者进程的功能:生产东西,供消费者消费;消费者进程的功能:消费
生产者生产的东西。生产者生产产品并存入缓冲区供消费者取走使用,消费者
从缓冲器内取出产品去消费 。在生产者和消费者同时工作时,必须禁止生产者将
return FALSE; }
//找出当前可以进行产品生产的空缓 冲区位置; int FindProducePosition() { int EmptyPosition; for (int i =0;i<n_Buffer_or_Critical;i++)
if(Buffer_Critical[i] == -1){ EmptyPosition = i; //用下面这个特殊值表示本缓冲区正处于被写状 态; Buffer_Critical[i] = -2; break;
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系统进程-进程互斥实验-进程的控制实验-实验0304

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),然后杀死进程。
操作系统_线程的同步与互斥

操作系统实验报告实验名称:线程的同步与互斥专业班级:网络工程1301学号:姓名:2015 年4 月7 日实验二线程的同步与互斥一、实验目的1、掌握程序中线程的操作。
2、熟悉线程不同步时的现象及环境因素。
3、掌握线程中同步和互斥对象的使用。
二、实验内容与步骤1.多线程访问共享变量(互斥)(1)定义类变量int i = 0; 初始值置为0,创建两个线程,一个对i 执行加 1 操作,另一个对i 执行减 1 操作。
两个线程执行相同的次数。
(2)观察两个线程执行后的情况,可以发觉最后i 的值不一定是0,这就是多个线程在操作一个共享变量i时,未互斥访问带来的严重问题。
(3)给这两个线程加上互斥操作的代码,再来观察对 i 值的影响。
添加互斥操作前添加互斥操作后2.通过多线程模拟“生产者—消费者”问题(同步)(1)定义一个数组用来模拟共享缓冲区,定义一个生产者线程和一个消费者线程来实现对数组进行读写。
(2)观察两个线程执行后的情况,看会不会出现读取数据重复和写入数据覆盖的情况,加入两步操作后再观察结果如何。
(3)创建多个生产者线程和消费者线程,再查看运行结果。
添加互斥操作前添加互斥操作后四、实验总结通过本次实验进一步熟悉了程序中线程的操作和线程中同步和互斥对象的使用,基本上理解了计算机系统中资源冲突的解决方法,也理解了线程不同步时的现象及环境因素,学会怎样使用系统和程序中资源冲突的方法,并且进一步了解了操作系统内部的知识,拓宽了我的视野和能力!五、程序清单1.多线程访问共享变量(互斥)using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace AddSub{class Program{static void Main(string[] args){AddAndSub ass = new AddAndSub();Thread add_Td = new Thread(ass.getAdd);Thread sub_Td = new Thread(ass.setSub);add_Td.Start();sub_Td.Start();add_Td.Join();sub_Td.Join();Console.WriteLine("最终结果:--"+ass.num);Console.Read();}}public class AddAndSub{public int num = 0;public AddAndSub(){ }public void getAdd(){lock (this){int i = 1000000;while (i != 0){num++;i--;}}}public void setSub(){lock (this){int j = 1000000;while (j != 0){num--;j--;}}}}}2.通过多线程模拟“生产者—消费者”问题(同步)using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace ConsumerAndProduct{class Program{static void Main(string[] args){BufferForDefine buffer=new BufferForDefine ();Producer producer = new Producer(buffer);Consumer consumer = new Consumer(buffer);//初始化了生产者和消费者,并且把shared参数传递了过去Thread producerThread = new Thread(new ThreadStart(producer.produce)); = "生产者";//定义了一个producerThread线程,new Thread是构造Thread //后面的那个new 则是启动一个新的线程,线程启动的方法是producer1.produceThread consumerThread = new Thread(new ThreadStart(consumer.consume)); = "消费者";//同上producerThread.Start();consumerThread.Start();//启动这两个线程Console.Read();}}public class BufferForDefine{private int[] buffer = { 1, 2, 3, 4, 5, 6, 7 };private int bufferCount = 0;private int readLocation = 0, writeLocation = 0;public BufferForDefine(){ }public int GetBuffer(){lock (this){if (bufferCount == 0){Console.WriteLine("缓冲区无数据,消费者无法读取"); Monitor.Wait(this);}Console.WriteLine("当前索引 " + readLocation);int readValue = buffer[readLocation];bufferCount--;//已经从缓冲区读取了内容,所以bufferCount要进行自减. readLocation = (readLocation + 1) % buffer.Length;//求余的目的是为了循环使用缓冲区Monitor.Pulse(this);//通知对象的第一个等待线程可以从WaitSleepJoin转换到Started状态.return readValue;//返回给consumer取出的数值}}public void setBuffer(int writeValue){lock (this){if (bufferCount == buffer.Length){Console.WriteLine("缓冲区!");Monitor.Wait(this);}//如果缓冲区已满,那么进入waitsleepjoin状态Console.WriteLine("当前索引 " + writeLocation);buffer[writeLocation] = writeValue;//向缓冲区写入数据bufferCount++;//自加,代表缓冲区现在到底有几个数据writeLocation = (writeLocation + 1) % buffer.Length; //用%实现缓冲区的循环利用Monitor.Pulse(this);//唤醒waitSleepJoin状态的进程,到started状态}}}public class Producer{BufferForDefine buffer;public Producer(BufferForDefine buffer){this.buffer = buffer;}public void produce()//定义生产过程{for (int count = 1; count <= 100; count++){buffer.setBuffer(count);Console.WriteLine("生产者向缓冲区中写入 " + count); }//将数据放入缓冲区string name = ;//得到当前线程的名字Console.WriteLine(name + "done producing");//此线程执行完毕}}public class Consumer{int value;BufferForDefine buffer;public Consumer(BufferForDefine buffer){this.buffer = buffer;}public void consume(){for (int count = 1; count <= 100; count++){value = buffer.GetBuffer();Console.WriteLine("消费者从缓冲中读取了数据" + value);}//从缓冲区中循环读取string name = ;//取得当前线程的名字Console.WriteLine(name + "done consuming");}}}。
山东大学操作系统实验报告4进程同步实验
计算机科学与技术学院实验报告int msq_id;if((msq_id = get_ipc_id("/proc/sysvipc/msg",msq_h)) < 0 ) { if((msq_id = msgget(msq_h,msq_flg)) < 0){perror("messageQueue set error");exit(EXIT_FAILURE);}}return msq_id;}实验结果:分析:多进程的系统中避免不了进程间的相互关系。
进程互斥是进程之间发生的一种间接性作用,一般是程序不希望的。
通常的情况是两个或两个以上的进程需要同时访问某个共享变量。
我们一般将发生能够问共享变量的程序段称为临界区。
两个进程不能同时进入临界区,否则就会导致数据的不一致,产生与时间有关的错误。
解决互斥问题应该满足互斥和公平两个原则,即任意时刻只能允许一个进程处于同一共享变量的临界区,而且不能让任一进程无限期地等待。
进程同步是进程之间直接的相互作用,是合作进程间有意识的行为,典型的例子是公共汽车上司机与售票员的合作。
只有当售票员关门之后司机才能启动车辆,只有司机停车之后售票员才能开车门。
司机和售票员的行动需要一定的协调。
同样地,两个进程之间有时也有这样的依赖关系,因此我们也要有一定的同步机制保证它们的执行次序。
信号量机制就是其中的一种。
信号灯机制即利用pv操作来对信号量进行处理。
PV操作由P操作原语和V 操作原语组成(原语是不可中断的过程),对信号量进行操作,具体定义如下: P(S):①将信号量S的值减1,即S=S-1;②如果S³0,则该进程继续执行;否则该进程置为等待状态,排入等待队列。
V(S):①将信号量S的值加1,即S=S+1;②如果S>0,则该进程继续执行;否则释放队列中第一个等待信号量的进程。
PV操作的意义:我们用信号量及PV操作来实现进程的同步和互斥。
实验四 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。
山东大学操作系统实验报告4进程同步实验
山东大学操作系统实验报告4进程同步实验计算机科学与技术学院实验报告实验题目:实验四、进程同步实验学号:日期:20120409 班级:计基地12 姓名:实验目的加深对并发协作进程同步与互斥概念的理解,观察和体验并发进程同步与互操作的效果,分析与研究经典进程同步与互斥问题的实际解决方案了 Linux 系统 IPC进程同步工具的用法,练习并发协作进程的同步与互斥操作的编与调试技术实验内容抽烟者问题假设一个系统中有三个抽烟者进程每个抽烟者不断地卷烟并抽烟抽烟者卷起并抽掉一颗烟需要有三种材料烟草纸和胶水一个抽烟者有烟草一个有纸,另一个有胶水。
系统中还有两个供应者进程,它们无限地供应所有种材料但每次仅轮流提供三种材料中的两种。
得到缺失的两种材料的抽烟者卷起并抽掉一颗烟后会发信号通知供应者让它继续提供另外的两种材料。
这过程重复进行请用以上介绍 IPC同步机制编程实现该问题要求的功能硬件环境@CPUi3-2350MIntel?Cor42.30GHz MobileIntel?Sandybridgex86/MMX/SSE24G内存3操作系统:20.1 GB磁盘:软件环境:ubuntu13.04实验步骤:(1)新建定义了producer和consumer 共用的文件。
ipc.h函数原型和变量的IPC.(2)新建ipc.c文件,编写producer和consumer共用的IPC的具体相应函数。
(3)新建Producer文件,首先定义producer的一些行为,利用系统调用建立共享内存区域,设定其长度并获取共享内存的首地址。
然后设定生产者互斥与同步的信号灯,并为他们设置相应的初值。
当有生产者进程在运行而其他生产者请求时,相应的信号灯就会阻止他,当共享内存区域已满时,信号等也会提示生产者不能再往共享内存中放入内容。
(4)新建Consumer文件,定义consumer的一些行为,利用系统调用来创建共享内存区域,并设定他的长度并获取共享内存的首地址。
(超详细)西电软院操作系统实验报告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、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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():向线程发送一个信号。