1、熟悉并发程序实验工具BACI。 2、掌握BACC和BAINTERP的使用。 3、熟悉信号量的同步控制机制。 二、实验软硬件要求 1、CPU:P4 1.6GHz 内存:4G 2、Windows平台上的Linux虚拟机
(1)完成Linux系统的登录,启动进入终端。 编程步骤: cd baci/balnxxe 编写程序文件命令:gedit my.cm (程序源码请看第(2)题,需要你补充缺失的代码。) 编译命令:$./bacc my,生成my.pco文件; 运行:./bainterp my.pco, 得到并分析结果。 (2)用信号量实现进程同步时,通常设置与进程相关的私有信号量。empty和full分别属于生产者和消费者进程私有,即生产者要问是否empty,才能开始生产;同理,消费者要问是否full才能消费。 用信号量mutex实现进程互斥,互斥使用缓冲池,其初值=1; 请将下面的并发程序填写完整,或自行编写并发程序。 参考程序:pc.cm semaphore mutex=1; //缓冲池互斥信号量 semaphore full=0; //满缓冲区个数信号量,初值=0 semaphore em=7; //空缓冲区个数信号量,初值=7 int in=0;int out=0; int buff[6]; //缓冲池 void p1() { int nextp; while(1) { cin>>nextp; //生产一个产品 p(em); //填写代码 buff[in]=nextp; cout <<"in="<<in<<endl; //填写代码; cout <<"nextp="<<nextp<<endl; v(mutex); //填写代码; } }//producer void c1() { int nextc; while(1) { //填写代码; p(mutex);
//填写代码 out=(out+1)%6; cout <<"nextc="<<nextc<<endl; //填写代码; v(em); } }//consumer void main() { cobegin{ p1();c1(); } } 完整代码: semaphore mutex=1; semaphore full=0; semaphore em=7; int in=0;int out=0; int buff[6]; void p1(){ int nextp; while(1){ cin>>nextp; p(em); p(mutex); buff[in]=nextp; cout<<"in="<<in<<endl; in=(in+1)%6; cout<<"nextp="<<nextp<<endl; v(mutex); v(full); } } void c1(){ int nextc; while(1){ p(full); p(mutex); nextc=buff[out]; out=(out+1)%6; cout<<"nextc="<<nextc<<endl; v(mutex); v(em); } }//consumer void main(){ cobegin{ p1(); c1(); } } (3)有父亲、母亲、儿子、女儿4个进程,共享一个盘子,父亲每次在盘子中放入一个苹果,盘子中的苹果只能由女儿取出;母亲每次向盘子放入一个桔子,桔子只能由儿子取出,假设盘子内能装一个水果。编程:apple.cm 1)编写用信号量机制实现父亲等4个进程的并发控制程序; 2)在BACI环境中运行并分析结果。 semaphore mutex=1; semaphore plat=1; semaphore apple=0; semaphore orange=0 ; int ap=0;int or=0;int pl=1; void father(){ int num; while(1){ p(plat); p(mutex); cin>>num; cout<<"father put on apple "<<num<<endl; v(apple); ap++; pl--; v(mutex);
} } void monther(){ int num; while(1){ p(plat); p(mutex); cin>>num; cout<<"monther put on orange "<<num<<endl; v(orange); or++; pl--; v(mutex);
} } void son(){ int num; while(1){ p(orange); p(mutex); cout<<"son take out a orange"<<endl; v(plat); or--; pl++; cout<<"orange="<<or<<endl; cout<<"plat="<<pl<<endl; v(mutex);
} } void daughter(){ int num; while(1){
p(apple); p(mutex); cout<<"daughter take out a apple"<<endl; v(plat); ap--; pl++; cout<<"apple="<<ap<<endl; cout<<"plat="<<pl<<endl; v(mutex);
} } void main(){ cobegin{ father(); daughter(); monther(); son();
} } 三、实验结果分析 (对上述实验内容中的各题结果,进行分析讨论。并回答下列问题)
当进程互斥时或者涉及临界资源的争夺时,应该遵循前P后V的信号量设置原则
当进程同步时,应该遵循前V后P的原则,即先发生的进程完成后设置V信号量,后发生的进程发生前设置P信号量,同时注意,PV信号量应该成对出现。 四、总结:你对本次实验有什么体会或看法。 分析信号量问题时,应该先进行关系分析,找出同步和互斥的关系,根据同步关系前V后P ,互斥关系前P后V的原则对信号量进行设置。 注意:伪代码中设置的semaphore是信号量,只能用PV进行加减,不能使用++或—进行操作。 附BACI工具说明: BACI提供了一个可以编写并发程序的环境,在这个平台上,我们可以很容易的模拟程序的并发执行,在这种并行的编译环境中,可以把BACI中的一些语句嵌入到C++,C,Java等高等程序中,使程序可以并行执行 . 基于C++的BACI语法(C—BACI Compiler) 该语法结构是在C++语法结构的基础上,增加一些并发语句扩展而来,下面是在试验中需要用到的函数解释. 1. cobegin函数 在BACI系统中,并发进程与并发线程同步,多个进程可以并发的在cobegin 块中来并发执行,该函数必须在主函数中,语法结构为: cobegin { proc1(...);proc2(...);. . . . procN(...); } 其中每个进程并发随机执行,每次执行的顺序可能会不一样,当所有的进程接受后,该函数结束。 2. Semaphores/Binarysem 信号量的(Semaphores)机制可以更方便的实现进程同步,Semaphores是一种如C中”int”一样的类型,可以用来定义信号量类型的变量,Binarysem是一种二进制信号量,它所定义的变量只能取1或 0,用来表示互斥。 1)信号量的声明和初始化 semaphores a; binarysem s; 上面声明了两个信号量a,b,其中b为二进制信号量信号量按如下方式初始化: Initialsem(semaphores,interger); Initialsem(binarysem,0/1); 2)P(wait)/V(signal)函数 强大的PV操作与信号量一次很方便的解决了并发进程同步与互斥问题 函数原型: void p(semaphores &s); or void wait(semaphores &s); void v(semaphores &s); or void signal(semaphores &s); 函数说明: p(sem): 如果sem > 0,则sem减1,调用P的进程可以继续执行,如果sem=0,则该进程阻塞,该函 数操作是原子性的. v(sem): 如果v=0,或有进程阻塞,则将其唤醒,如果没有进程等待,将sem加1,在任何时候调用 v的进程可以继续执行,其操作也是原子的. 3.atomic atomic关键字定义了原子操作,即该函数操作不可剥夺,每次只能一个进程访问 用法:在要原子执行的函数前加atomic即可,如: atomic int sum(){ . . . .. } 则sum()函数就可以原子操作了 4.void suspend(void) suspend函数将调用的线程挂起 5.void revive (int process_number) 该函数用于唤醒某个进程,其进程号为process_number文章来源:https://www.toymoban.com/news/detail-741752.html 6.cin可以连续从键盘读取想要的数据,以空格、tab或换行作为分隔符。文章来源地址https://www.toymoban.com/news/detail-741752.html |
到了这里,关于操作系统原理及安全 3-并发程序设计(综合型)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!