如何使用消息队列在 C 中的进程之间获得随机暂停?

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

我正在编写一个使用进程间消息队列的 C 程序。我正在尝试重现进程 J(法官)和 n 个子进程之间的拍卖。程序从输入文件 txt 和一些子进程中获取。

这是我的代码:

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

#define MSG_SIZE sizeof(msg)-sizeof(long)
#define BUFFER 1024

typedef struct{
    long type;
    char id;
    int min_offerta;
    int max_offerta;
    long bindders_offert;
    char object[BUFFER];
    char done;
    long num_aste;
    char counter_done;
}msg;

void bidders(int id,int coda,int num_bidders){

    srand(time(NULL));
    msg messaggio;
    int wait;
    long offerta;

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

        if(messaggio.done){
            messaggio.counter_done++;
            break;
        }

        wait=rand()%3;

        printf("[B%d]: attendo per %d secondi\n",id,wait);
        
        sleep(wait);

        offerta=(rand()% messaggio.max_offerta);

        messaggio.bindders_offert=offerta;
        messaggio.id=id;

        if((msgsnd(coda,&messaggio,MSG_SIZE,0))==-1)
        {
            perror("msgsnd");
            exit(1);
        } 

        printf("[B%d] invio offerta di %d per asta n.%d per %s\n",id,offerta,messaggio.num_aste,messaggio.object);

    }

    if(messaggio.counter_done==num_bidders)
    {
        msgctl(coda,IPC_RMID,NULL);
    }

    exit(0);
}

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


    if(argc<3)
    {
        fprintf(stderr,"Utilizzo: %d <action-file> <num-bidders>\n",argv[0]);
        exit(1);
    }

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

    int num_bidders=atoi(argv[2]);

    
    for(int i=0; i<num_bidders; i++)
    {

        if(!fork())
            bidders(i+1,coda,num_bidders);  
    }

    FILE* file;
    char tmp[BUFFER];
    msg messaggio;
    long num_aste=0,aste_concluse=0,aste_nulle=0;
    char* path=argv[1], *min_offerta, *max_offerta,* object;
    int max=0,min=0;


    if((file=fopen(path,"r"))==NULL)
    {
        perror("fopen");
        exit(1);
    }

    while(fgets(tmp,BUFFER,file))
    {
        

        if(tmp[strlen(tmp)-1]=='\n')
        tmp[strlen(tmp)-1]='\0';

        num_aste++;
        messaggio.type=1;
        messaggio.done=0;
        messaggio.num_aste=num_aste;

        if((object=strtok(tmp,","))!=NULL)
        {
            
            if((min_offerta=strtok(NULL,","))!=NULL)
            {
                
                if((max_offerta=strtok(NULL,","))!=NULL)
                {
                    max=atoi(max_offerta);
                    min=atoi(min_offerta);
                    strncpy(messaggio.object,object,BUFFER);
                    
                }
            }
        }
        
        messaggio.max_offerta=max;
        messaggio.min_offerta=min;

        printf("[J] lancio asta n.%ld per %s con offerta minima di %d e massima di %d\n",num_aste,messaggio.object,messaggio.min_offerta,messaggio.max_offerta);

        if((msgsnd(coda,&messaggio,MSG_SIZE,0))==-1)
        {
            perror("msgsnd");
            exit(1);
        } 

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

        printf("[J] ricevo offerta di %ld da %d\n",messaggio.bindders_offert,messaggio.id);     
    }

    printf("[J]Exit\n");

    messaggio.type=1;
    messaggio.done=1;
    if((msgsnd(coda,&messaggio,MSG_SIZE,0))==-1)
    {
        perror("msgsnd");
        exit(1);
    }


    printf("Sono state svolte n.%ld aste!\n",num_aste);

}

输出应该是这样的:

J: lancio asta n.1 per Cotta di Mithril con offerta minima di 100 EUR e massima di 500 EUR
B2: aspetto per 0 secondi
B2: invio offerta di 334 EUR per asta n.1 per Cotta di Mithril
J: ricevuta offerta da B2
B1: aspetto per 1 secondi
B1: invio offerta di 221 EUR per asta n.1 per Cotta di Mithril
J: ricevuta offerta da B1
J: lancio asta n.2 per Palantìr con offerta minima di 700 EUR e massima di 1000 EUR
B4: aspetto per 3 secondi
B2: invio offerta di 409 EUR per asta n.2 per Palantìr
J: ricevuta offerta da B2
B4: aspetto per 0 secondi
B1: invio offerta di 99 EUR per asta n.2 per Palantìr
J: ricevuta offerta da B1
B4: aspetto per 3 secondi
B4: invio offerta di 598 EUR per asta n.2 per Palantìr
J: ricevuta offerta da B4
B3: aspetto per 2 secondi
B3: invio offerta di 650 EUR per asta n.2 per Palantìr
J: ricevuta offerta da B3
J:Exit
Sono state svolte n.2 aste!

但我的输出是:

[J] lancio asta n.1 per Cotta di Mithril con offerta minima di 100 e massima di 500
[B1]: attendo per 2 secondi
[B1] invio offerta di 72 per asta n.1 per Cotta di Mithril
[B2]: attendo per 2 secondi
[B2] invio offerta di 72 per asta n.1 per Cotta di Mithril
[J] ricevo offerta di 72 da 2
[J] lancio asta n.2 per Palantír con offerta minima di 700 e massima di 1000
[B1]: attendo per 2 secondi
[B1] invio offerta di 281 per asta n.2 per Palantír
[B2]: attendo per 2 secondi
[B2] invio offerta di 281 per asta n.2 per Palantír
[J] ricevo offerta di 281 da 2
[J]Exit
Sono state svolte n.2 aste!

为什么进程J只拿到最后的offer?为什么我不能在两个进程之间生成不同的随机暂停?我哪里做错了?

c ipc message-queue
© www.soinside.com 2019 - 2024. All rights reserved.