linux操作系统-综合编程

【实验内容】

  1. 编写C程序,使用Linux操作系统中的信号量机制模拟解决经典的进程同步问题;生成者-消费者问题。假设有一个生成者和一个消费者,缓冲区可以存放产品,生成者不断生产产品并存入缓冲区,消费者不断从缓冲区中取出产品并消费。
  2. 编写C程序,使用Linux中的IPC机制完成“石头、剪刀、布”游戏。使之能够在网络上运行。

【实验目的】

  1. 加强对进程同步和互斥的理解,学会使用信号量解决资源共享问题;
  2. 熟悉Linux进程同步原语;
  3. 掌握信号量wait/signal原语的使用方法,理解信号量的定义、赋初值及wait/signal操作;
  4. 理解进程间通信的概念和方法;
  5. 掌握常用的Linux进程间通信的方法。

实验技术

1.VMware Workstation

版本:15.5.0 build-14665864

作用:可在一部实体机器上模拟完整的网络环境,以及可便于携带的虚拟机器,在虚拟网路,实时快照,拖曳共享文件夹,支持 PXE 等方面的特点使它成为必不可少的工具。

2.Ubuntu系统

版本:Ubuntu20.04

作用: Ubuntu是一个基于Debian的以桌面应用为主的Linux操作系统, Ubuntu的目标在于为一般用户提供一个最新同时又相当稳定,主要以自由软件建构而成的操作系统。Ubuntu目前具有庞大的社区力量支持,用户可以方便地从社区获得帮助。

【实验原理/思路】  

  • 针对实验内容(1),可以创建三个进程,其中一个进程为裁判进程,另外两个进程为选手进程。可将“石头”“剪刀”“布”这三招定义为三个整型值,胜负关系为:石头>剪刀>布>石头。
  • 选手进程按照某种策略(如随机产生)出招,然后交给裁判进程判断大小。裁判进程将对手的出招和胜负结果通知选手。比赛采取多轮(如100轮)定胜负机制,并由裁判宣布最后结果。每次出招由裁判限定时间,超时则判负。
  • 每一轮的胜负结果可以存放在文件或其他数据结构中。比赛结束后,打印每一轮的胜负情况和总的结果。具体的实验步骤如下。

(1)设计表示“石头”“剪刀”“布”的数据结构以及它们之间的大小规则;

(2)设计比赛结果的存放方式;

(3)选择IPC方法;

(4)根据所选择的IPC方法,创建对应的IPC 资源;

(5)完成选手进程;

(6)完成裁判进程。

实验步骤与实验结果】

一、生成者-消费者问题

1.源代码

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

#include <pthread.h>

#include <semaphore.h>

#define NUM 5

int queue[NUM];

sem_t sem_blank,sem_food;//空盘子,包子

void producer(){int i=0;

    while (1){ sem_wait(&sem_blank);

        queue[i]=rand()%100+1;

        sem_post(&sem_food);

        printf("producer queue[%d] is : %d\n",i,queue[i]);

        i++;

        i=i%5;

        sleep(rand()%3);

 }}

void consumer(){

    int i=0;

    while (1){

        sem_wait(&sem_food);

        printf("consumer queue[%d] is %d\n",i,queue[i]);

        queue[i]=0;

        sem_post(&sem_blank);

        i++;

        i=i%5;

        sleep(rand()%3); }}

int main(void){

    int ret;

    ret=sem_init(&sem_blank,0,5);//value值就表示桌子上有几个盘子

    if (ret==-1){ perror("[sem_blank]");

        return -1; }

    ret=sem_init(&sem_food,0,0);//value值表示桌子上有几个包子

    if (ret==-1){ perror("[sem_food]");

        return -1; }

    //创建两个线程,生产者,消费者

    pthread_t tid1,tid2;

    while ((pthread_create(&tid1,NULL,(void *)producer,NULL))!=0);

    while ((pthread_create(&tid2,NULL,(void *)consumer,NULL))!=0);

    //回收线程

    pthread_join(tid1,NULL);

    pthread_join(tid2,NULL);

}

2.运行结果

二、“石头、剪刀、布”游戏

1.源代码

#include <unistd.h>

#include<fcntl.h>

#include<stdio.h>

#include<sys/types.h>

#include<sys/stat.h>

#include<errno.h>

#include<stdlib.h>

#include<string.h>

#include<time.h>

#include<sys/wait.h>

int judge(char a,char b);



int main(void)

{

 int fd1,fd2,fd3,fd4,i=0;

 int status;

 char * myfifo1 = "/tmp/myfifo1";

 char * myfifo2 = "/tmp/myfifo2";

 char * myfifo3 = "/tmp/myfifo3";

 char * myfifo4 = "/tmp/myfifo4";

 char start[1] = {'3'};

 char end[1] = {'4'};

 char c1[1];//用来存放p1发送的消息

 char c2[2];//用来存放p2发送的消息

 char s1[1];//用来存放裁判发送的消息

 char s2[2];//用来存放裁判发送的消息

 int p1w=0,p2w=0,pd=0;

if((mkfifo(myfifo1,0666)<0)&&(errno!=EEXIST))

{

   printf("cannot create fifo.\n");

   exit(1);

}

if((mkfifo(myfifo2,0666)<0)&&(errno!=EEXIST))

{

   printf("cannot create fifo.\n");

   exit(1);

}

if((mkfifo(myfifo3,0666)<0)&&(errno!=EEXIST))

{

   printf("cannot create fifo.\n");

   exit(1);

}

if((mkfifo(myfifo4,0666)<0)&&(errno!=EEXIST))

{

   printf("cannot create fifo.\n");

   exit(1);

}

 pid_t p1 = fork();

 /*********************************/

 if(p1==0)

 {

  srand(time(NULL));

  while(1)

  {

   i++;

   fd1 = open(myfifo1,O_RDONLY);

   read(fd1,s1,1);

   close(fd1);

   if(s1[0] == '3')

   {

    fd3 = open(myfifo3,O_WRONLY);

    int j = rand()%3;

    s1[0] = j + '0';

    write(fd3,s1,strlen(s1)+1);

    close(fd3);

   

   }else if(s1[0] == '4'){

    exit(0);   

   }

  }

  return 0;

 }

 pid_t p2=fork();

/*********************************/

 if(p2==0)

 {

  srand(time(NULL)+100);

  while(1)

  {

   i++;

   fd2 = open(myfifo2,O_RDONLY);

   read(fd2,s2,1);

   close(fd2);

   if(s2[0] == '3')

   {

    fd4 = open(myfifo4,O_WRONLY);

    int j = rand()%3;

    s2[0] = j + '0';

    write(fd4,s2,strlen(s2)+1);

    close(fd4);

   

   }else if(s2[0] == '4'){



    exit(0);   

   }

  }

  return 0;

 }



//比赛场地



while(1)

{

if(p1 != 0 && p2!=0){

 i++;

 if(i>100)

 {

  fd1 = open(myfifo1,O_WRONLY);

  fd2 = open(myfifo2,O_WRONLY);

  write(fd1,end,strlen(start)+1);

  write(fd2,end,strlen(start)+1);

  close(fd1);

  close(fd2);

  break;

 }

 printf("这是第 %d 轮\n",i);

 fd1 = open(myfifo1,O_WRONLY);

 fd2 = open(myfifo2,O_WRONLY);

 //向管道1,2中写入开始出拳信号start

 write(fd1,start,strlen(start+1));

 write(fd2,start,strlen(start+1));

 close(fd1);

 close(fd2);

 sleep(1);

 fd3 = open(myfifo3,O_RDONLY);

 fd4 = open(myfifo4,O_RDONLY);

 //从管道3,4中读出比赛选手出拳情况

 read(fd3,c1,sizeof(c1));

 read(fd4,c2,sizeof(c2));

 //打印一轮结果

 printf("p1: %c\n",c1[0]);

 printf("p2: %c\n",c2[0]);

 close(fd3);

 close(fd4);

int tmp = judge(c1[0],c2[0]);

 if(tmp==0)

  {

   printf("in a draw!\n");

   pd++;//平局

  }

  else

  {

   printf("%s wins!\n",(tmp>0)?"p1":"p2");

   if(tmp>0){

    p1w++;//p1胜

    }

   else {

   p2w++;    //p2胜

   }

  }

}

}

//打印最终统计结果

printf("In summary:\n");

printf("p1 wins %d  rounds.\n",p1w);

printf("p2 wins %d  rounds.\n",p2w);

printf("%d rounds end in a draw.\n",pd);

printf("%s wins in the game!\n",(p1w>p2w)?"p1":"p2");

}

//0——石头,1——剪刀,2——布

int judge(char a,char b)//规定游戏判定规则

{

 int r=0;

 if(a==b){

 r=0;}

 else

 {

   if(a=='0'&&b=='1')r=1;

   if(a=='0'&&b=='2')r=-1;

   if(a=='1'&&b=='2')r=1;

   if(a=='1'&&b=='0')r=-1;

   if(a=='2'&&b=='0')r=1;

   if(a=='2'&&b=='1')r=-1;

 }

 return r;

}

2.运行结果

【实验小结】

        在这次实验的过程中,通过学习gcc编译全过程,了解到linux系统编译c语言和win10编译的差异,通过总结的动手和尝试,深刻了解到如何去编译和运行c语言代码。C语言编程是计算机编程学习的基本技能, 在利用C语言编程时可以将C语言和Linux系统结合起来, 掌握Linux系统、C语言编程的各类技巧, 才能熟练掌握和应用两种技术, 提高程序编写质量和效率。更加了解Linux一些常用指令的操作以及其作用,对于一个刚开始接触lniux操作系统的初学者来说非常有用,有助于以后能够更进一步学习Linux操作系统

  • 3
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值