如何在 C 中使用进程间通信进行正确的消息队列?

问题描述 投票:0回答:1

我试图在 C 中使用消息队列模拟宾果游戏。 我的程序是这样做的:

  • 爸爸发给孩子的卡片,不分先后顺序
  • 孩子们收到卡片并打印在标准输出上。

程序从输入中获取孩子的数量和卡的数量。

问题是当我运行程序时,并不是所有的孩子都能拿到卡片,我收到了错误消息 queque 。我想我错了过程通信。

我的密码是:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <time.h>


#define MSG_SIZE sizeof(msg)-sizeof(long)
#define R 3
#define C 5

typedef struct{
    long type;
    int card[R][C];
    char done;
    char cinquina;
    char bingo;
}msg;

void print_card(int matrix[R][C]){

    for(int i=0; i<R; i++)
    {
        printf("(");
        for(int j=0; j<C; j++)
        {
            if(j==C-1)
                printf("%d",matrix[i][j]);
            else
                printf("%d,",matrix[i][j]);
            
        }
        if(i==R-1)
            printf(")\n");
        else
            printf(")/");
    }
}

void generate_card(int matrix[R][C]){

    for(int i=0; i<R; i++)
    {
        for(int j=0; j<C; j++)
        {
            matrix[i][j]=rand()%75+1;
        }
    }
}


void init_matrix(int matrix[R][C]){

    for(int i=0; i<R; i++)
    {
        for(int j=0; j<C; j++)
        {
            matrix[i][j]=0;
        }
    }
}


void player(int coda, char id,int n_card){
    msg message;
    char card_counter=0;
    message.done=0;
    message.type=1;

    while(1)
    {
        if(msgrcv(coda,&message,MSG_SIZE,0,0)==-1)
        {
            perror("msgrcv player");
            exit(1);
        }

        if(card_counter==n_card)
            break;
        else {

            printf("[P%d] : received card ",id);
            print_card(message.card);
            card_counter++;
        }
    }
}


int main(int argc,char* argv[]){

    int coda;

    if(argc!=3)
    {
        fprintf(stderr,"How to use: %s <n> <m> \n",argv[0]);
        exit(1);
    }

    if((coda=msgget(IPC_PRIVATE,IPC_CREAT|0600))==-1)
    {
        perror("msgget");
        exit(1);
    }

    int n_player=atoi(argv[1]);//number player
    int n_card=atoi(argv[2]);//number cards

    for(int i=0; i<n_player; i++)
    {
        if(!fork())
            player(coda,i+1,n_card);

    }
    
    int matrix[R][C];
    srand(time(NULL));
    msg message;


    for(int j=0; j<n_card*n_player; j++)
    {
        printf("[D] I generate and distribute card n.%d: ",j+1);
        init_matrix(message.card);
        generate_card(message.card);
        print_card(message.card);
        
        message.type=1;
            
        if(msgsnd(coda,&message,MSG_SIZE,0)==-1)
        {
            perror("msgsnd dealer");
            exit(1);
        }
    }
        

    for(int i=0; i<n_player; i++)
        wait(NULL);

    msgctl(coda,IPC_RMID,NULL);

}

这是错误的输出:

parallels@debian-gnu-linux-11:~/Desktop/sistemi-operativi/code/bingo$ ./bingo 2 2
[D] I generate and distribute card n.1: (36,40,32,70,71)/(17,74,28,55,71)/(42,73,39,21,72)
[D] I generate and distribute card n.2: (42,11,11,53,43)/(37,73,3,3,24)/(5,7,54,33,73)
[D] I generate and distribute card n.3: (18,68,14,50,62)/(10,66,37,37,22)/(33,55,20,48,52)
[D] I generate and distribute card n.4: (16,66,63,26,43)/(30,39,40,9,41)/(41,13,48,19,45)
[P1] : received card (36,40,32,70,71)/(17,74,28,55,71)/(42,73,39,21,72)
[P1] : received card (18,68,14,50,62)/(10,66,37,37,22)/(33,55,20,48,52)
[D] I generate and distribute card n.1: (36,40,32,70,71)/(17,74,28,55,71)/(42,73,39,21,72)
[D] I generate and distribute card n.2: (42,11,11,53,43)/(37,73,3,3,24)/(5,7,54,33,73)
[D] I generate and distribute card n.3: (18,68,14,50,62)/(10,66,37,37,22)/(33,55,20,48,52)
[D] I generate and distribute card n.4: (16,66,63,26,43)/(30,39,40,9,41)/(41,13,48,19,45)
[P2] : received card (36,40,32,70,71)/(17,74,28,55,71)/(42,73,39,21,72)
[P2] : received card (42,11,11,53,43)/(37,73,3,3,24)/(5,7,54,33,73)
[D] I generate and distribute card n.1: (36,40,32,70,71)/(17,74,28,55,71)/(42,73,39,21,72)
[D] I generate and distribute card n.2: (42,11,11,53,43)/(37,73,3,3,24)/(5,7,54,33,73)
[D] I generate and distribute card n.3: (18,68,14,50,62)/(10,66,37,37,22)/(33,55,20,48,52)
[D] I generate and distribute card n.4: (16,66,63,26,43)/(30,39,40,9,41)/(41,13,48,19,45)
[P2] : received card (42,11,11,53,43)/(37,73,3,3,24)/(5,7,54,33,73)
msgrcv player: Invalid argument

为什么父亲两次生成4张牌?

输出sd应该是这样的:

parallels@debian-gnu-linux-11:~/Desktop/sistemi-operativi/code/bingo$ ./bingo 2 2
[D] I generate and distribute card n.1: (3,52,72,29,21)/(32,36,18,42,49)/(71,49,32,54,2)
[D] I generate and distribute card n.2: (57,55,72,43,69)/(3,11,73,24,75)/(27,71,4,52,50)
[D] I generate and distribute card n.3: (28,54,26,1,59)/(23,32,19,40,74)/(44,13,24,52,43)
[D] I generate and distribute card n.4: (2,33,74,73,1)/(44,75,63,42,1)/(63,45,48,43,21)
[P2] : received card (3,52,72,29,21)/(32,36,18,42,49)/(71,49,32,54,2)
[P1] : received card (28,54,26,1,59)/(23,32,19,40,74)/(44,13,24,52,43)
[P2] : received card (57,55,72,43,69)/(3,11,73,24,75)/(27,71,4,52,50)
[P1] : received card (2,33,74,73,1)/(44,75,63,42,1)/(63,45,48,43,21)

任何人都可以帮助我吗?

c operating-system ipc
1个回答
0
投票

在此代码中:

for(int i=0; i<n_player; i++)
    {
        if(!fork())
            player(coda,i+1,n_card);

    }

player()
回来时会发生什么? 当玩家返回时,玩家应该调用 _exit(),或者 main 应该调用..

© www.soinside.com 2019 - 2024. All rights reserved.