进程通信实验报告

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 .实验名称 进程通信 |
| 1. 实验目的 (1)理解进程间通信的概念和方法。 (2)掌握常用的Linux进程间通信的方法。 |
| 1. 实验内容 (1)编写C程序,使用Linux中的IPC机制,完成"石头、剪子、布"的游戏。 (2)修改上述程序,使之能够在网络上运行该游戏。 |
| 4. 实验原理或流程图 消息队列的概念: 消息队列是一种进程间通信机制,允许不同进程之间通过发送和接收消息来交换数据。 每个消息队列都有一个唯一的标识符(key),用于区分不同的队列。 消息队列的创建: 使用msgget()系统调用创建消息队列,需要提供键值(key)和权限(perm)。 IPC_CREAT标志用于创建一个新的消息队列,如果队列已存在则返回现有的队列。 0666是权限掩码,表示任何用户都可以读写消息队列。 消息结构: 消息队列中的消息通常包含一个long类型的消息类型(Type)和一个指向消息数据的指针。 在这份代码中,消息数据是自定义的结构体Game,包含轮次(Round)和消息类型(Type)。 发送消息: 使用msgsnd()系统调用向消息队列发送消息。 需要提供消息队列的标识符(msgid)、指向消息结构的指针、消息长度和标志位(0表示不截断消息)。 接收消息: 使用msgrcv()系统调用从消息队列接收消息。 需要提供消息队列的标识符(msgid)、指向消息结构的指针、消息长度、消息类型和标志位(0表示接收第一个消息)。 消息队列的操作: msgctl()系统调用用于控制消息队列,如删除消息队列(IPC_RMID)。 消息队列的删除: 在程序结束时,应该使用msgctl()系统调用删除消息队列,释放系统资源。 消息队列的同步: 消息队列本身不提供同步机制,需要通过其他方式(如信号量、互斥锁)来确保消息的发送和接收顺序。 消息队列的容量: 消息队列有一个最大消息数和每个消息的最大长度限制,这些限制取决于系统配置。 错误处理: 如果msgget()、msgsnd()或msgrcv()调用失败,它们会返回-1,并设置全局变量errno以指示错误类型 |

cpp 复制代码
#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <time.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <sys/ipc.h>

#include <sys/msg.h>

struct Game   //游戏信息

{

    int Round;

    long Type;

};

void result_send(int num)     //发送出拳信息

{

    struct Game game;

    game.Type = 1;

    game.Round = rand() % 3;

    msgsnd(num, &game, sizeof(int), 0);

}

int result_announce(int a, int b)    //出拳结果的判断

{

    if ((a + 1 == b) || (a - 3 == b))

        return -1;    //a胜b

    else if (a == b)

        return 0;    //ab平局

    else

        return 1;    //a负b

}

void writeFile(int *result_list, int len)   //将每盘的结果存入文件

{

    int count_A = 0;

    int count_B = 0;

    int pingju=0;

    FILE *fin;

    if( (fin = fopen( "result.txt", "w" )) == NULL )

        printf( "This file wasn't opened" );



    int i;

    for (i = 0; i < len ; i++)

    {

        switch(result_list[i])

        {

            case -1 :{

                count_A++;

                fprintf(fin, "NO.%d:A win\n", i + 1);

                printf("NO.%d:A win\n", i + 1);

                break;

            }

            case 0 : {

                pingju++;

                fprintf(fin, "NO.%d:end in a draw\n", i + 1);

                printf("NO.%d:end in a draw\n", i + 1);

                break;

            }

            case 1 : {

                count_B++;

                fprintf(fin, "NO.%d:B win\n", i + 1);

                printf("NO.%d:B win\n", i + 1);

                break;

            }

        }

    }



    printf("\nThe final result is A win:%ds \nB win:%ds \nend in a draw %ds\n",count_A,count_B,pingju);

    fprintf(fin, "\nThe final result is A win:%ds \nB win:%ds \nend in a draw %ds\n",count_A,count_B,pingju);

    fclose(fin);

}

int main()

{

    int times;

    int key1 = 1234;

    int key2 = 5678;

    int *result_list;

    pid_t  pid1, pid2; 

    int msgid1,msgid2;

    msgid1 = msgget(key1, IPC_CREAT | 0666); //创建消息队列

    if(msgid1 == -1)

    {

        fprintf(stderr, "failed with error");

        exit(EXIT_FAILURE);

    }

    msgid2 = msgget(key2, IPC_CREAT | 0666); //创建消息队列

    if(msgid2 == -1)

    {

        fprintf(stderr, "failed with error");

        exit(EXIT_FAILURE);

    }

    printf("Game start,please input rounds:");

    scanf("%d", &times);

    result_list=(int*)malloc(times*sizeof(int));

    int i;

    for (i = 0; i < times; i++)

    {

        pid1 = fork();   //创建选手1

        if (pid1 == 0)

        {

            srand((unsigned)time(0) * 3000 ); //以时间为种子

            result_send(msgid1);  //生成选手1的出拳信息并发送到信息队列

            exit(-1);

        }

        pid2 = fork();   //创建选手2

        if (pid2 == 0)

        {

            srand((unsigned)time(NULL)*i ); //以时间为种子

            result_send(msgid2);  //生成选手2的出拳信息并发送到信息队列

            exit(-1);

        }

        if (pid1 < 0 || pid2 < 0)

        {

            fprintf(stderr, "Fork Failed");

            exit(-1);

        }

        else

        {

            wait(NULL);

            wait(NULL);

            struct Game game1;

            struct Game game2;

//printf("wait ok.\n");

      //从消息队列中取得选手1的出拳信息

            msgrcv(msgid1, &game1, sizeof(game1) - sizeof(long), 0, 0);

//printf("rcv1 ok.\n");

       //从消息队列中取得选手2的出拳信息

            msgrcv(msgid2, &game2, sizeof(game2) - sizeof(long), 0, 0);

       //评判出拳结果

//printf("rcv2 ok.\n");

            int j = result_announce(game1.Round, game2.Round);

 //result_list[i] = result_announce(game1.Round, game2.Round);

            result_list[i] = j;

        }

    }

//printf("end ok.\n");

    //将比赛结果写入文件

    writeFile(result_list, times);

    //删除消息队列

    if (msgctl(msgid1, IPC_RMID, 0) == -1)

    {

        fprintf(stderr, "msgctl(IPC_RMID) failed\n");

    }

    if (msgctl(msgid2, IPC_RMID, 0) == -1)

    {

        fprintf(stderr, "msgctl(IPC_RMID) failed\n");

    }

   exit(EXIT_SUCCESS);}
相关推荐
add45a2 小时前
C++中的原型模式
开发语言·c++·算法
2401_844221322 小时前
C++类型推导(auto/decltype)
开发语言·c++·算法
2201_753877792 小时前
高性能计算中的C++优化
开发语言·c++·算法
无限进步_2 小时前
深入解析C++容器适配器:stack、queue与deque的实现与应用
linux·开发语言·c++·windows·git·github·visual studio
2501_945425152 小时前
分布式系统容错设计
开发语言·c++·算法
2401_884563242 小时前
C++代码重构实战
开发语言·c++·算法
fpcc2 小时前
跟我学C++中级篇—std::shared_ptr的线程安全性分析
开发语言·c++
2401_831920742 小时前
C++中的桥接模式
开发语言·c++·算法
m0_743470372 小时前
C++中的桥接模式变体
开发语言·c++·算法