0


操作系统原理及安全 3-并发程序设计(综合型)

  • 实验目的

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();

}

}

三、实验结果分析

(对上述实验内容中的各题结果,进行分析讨论。并回答下列问题)

  1. 简述用信号量控制互斥问题时的编程设置。

当进程互斥时或者涉及临界资源的争夺时,应该遵循前P后V的信号量设置原则

  1. 简述用信号量控制同步问题时的编程设置。

当进程同步时,应该遵循前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(...);

  }

其中每个进程并发随机执行,每次执行的顺序可能会不一样,当所有的进程接受后,该函数结束。

  1. 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

6.cin可以连续从键盘读取想要的数据,以空格、tab或换行作为分隔符。


本文转载自: https://blog.csdn.net/m0_68597398/article/details/131882463
版权归原作者 忘崽奶糖~ 所有, 如有侵权,请联系我们删除。

“操作系统原理及安全 3-并发程序设计(综合型)”的评论:

还没有评论