1

The msgsnd() and msgrcv() are in the same function, it works well like the first example.

main.c

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>


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

    pid_t pid1;
    pid_t pid2;
    pid_t pid3;
    pid_t pid4;

    if ((pid1 = fork()) < 0) {
        printf("fork error\n");
    } else if (pid1 == 0){
        printf("I am in First process\n");
        int nodeId = 1;
        //cmc_init(nodeId);
        test2(nodeId);
        return 0;

    }

    if ((pid2 = fork()) < 0) {
        printf("fork error\n");
    } else if (pid2 == 0){
        printf("I am in second process\n");
        int nodeId = 2;
        //cmc_init(nodeId);
        test2(nodeId);
        return 0;

    } 

    if ((pid3 = fork()) < 0) {
        printf("pid3 fork error\n");
    } else if (pid3 == 0) {
        printf("I am in Third process\n");
        int nodeId = 3;
        //cmc_init(nodeId);
        test2(nodeId);
        return 0;
    } 

    if ((pid4 = fork()) < 0) {
        printf("pid4 fork error\n");
    } else if (pid4 == 0) {
        printf("I am in Fourth process\n");
        int nodeId = 4;
        //cmc_init(nodeId);
        //test2(nodeId);
        return 0;
    } 

    if (waitpid(-1, NULL, 0) < 0) {
        printf("wait1 error\n");
    }   
    sleep(3);


    return 0;
}

comproc.c

typedef struct Msg_context {
    int nodeId;

} Msg_context;
void test2(int nodeId)
{
    int i = 1;
    for (i = 1; i <= 3; i++) {
        if (i == nodeId) {
            continue;
        }
        int msgid = -1;
        Msg_context msgSend;

        msgid = msgget((key_t)i, 0666 | IPC_CREAT);


        if (msgid == -1) {
            printf("msgid == -1\n");
        }

        msgSend.nodeId = nodeId;
        if (msgsnd(msgid, (void *)&msgSend, 4, 0) == -1) {
            printf("send message error\n");
        }
    }

    //com_process_send(nodeId);

    sleep(1);
    while (1) {
        //com_process_recv(nodeId);
        int msgrecvId = -1;
        Msg_context msgRecv;
        msgrecvId = msgget((key_t)nodeId, 0666 | IPC_CREAT);


        if (msgrecvId == -1) {
            printf("msgrecvId == -1\n");
        }

        if (msgrcv(msgrecvId, (void *)&msgRecv, BUFSIZ, 0, 0) == -1) {
            printf("send message error\n");
        }
        printf("[recv] nodeId = %d, recv.nodeId = %d\n", nodeId, msgRecv.nodeId);

    }


}

It works well, the result:

I am in First process
[recv] nodeId = 2, recv.nodeId = 1
[recv] nodeId = 3, recv.nodeId = 1
I am in second process
[recv] nodeId = 1, recv.nodeId = 2
[recv] nodeId = 3, recv.nodeId = 2
I am in Third process
[recv] nodeId = 1, recv.nodeId = 3
[recv] nodeId = 2, recv.nodeId = 3
I am in Fourth process

but When I put the msgrcv() into another function, it dones't work well. Like this:

comproc.c

typedef struct Msg_context {
    int nodeId;

} Msg_context;
int com_process_recv(int nodeId)
{

    int msgrecvId = -1;
    Msg_context msgRecv;
    msgrecvId = msgget((key_t)nodeId, 0666 | IPC_CREAT);


    if (msgrecvId == -1) {
        printf("msgrecvId == -1\n");
    }

    if (msgrcv(msgrecvId, (void *)&msgRecv, BUFSIZ, 0, 0) == -1) {
        printf("send message error\n");
    }
    printf("[recv] nodeId = %d, recv.nodeId = %d\n", nodeId, msgRecv.nodeId);



}
void test2(int nodeId)
{
    int i = 1;
    for (i = 1; i <= 3; i++) {
        if (i == nodeId) {
            continue;
        }
        int msgid = -1;
        Msg_context msgSend;

        msgid = msgget((key_t)i, 0666 | IPC_CREAT);


        if (msgid == -1) {
            printf("msgid == -1\n");
        }

        msgSend.nodeId = nodeId;
        if (msgsnd(msgid, (void *)&msgSend, 4, 0) == -1) {
            printf("send message error\n");
        }
    }

    //com_process_send(nodeId);

    sleep(1);
    while (1) {
        com_process_recv(nodeId);


    }


}

The result is like this:

I am in First process
[recv] nodeId = 2, recv.nodeId = 1
I am in second process
[recv] nodeId = 1, recv.nodeId = 2
[recv] nodeId = 3, recv.nodeId = 2
I am in Third process
[recv] nodeId = 2, recv.nodeId = 3
[recv] nodeId = 1, recv.nodeId = 3
I am in Fourth process

or like this:

I am in First process
[recv] nodeId = 2, recv.nodeId = 1
[recv] nodeId = 3, recv.nodeId = 3, ret = 4
I am in second process
[recv] nodeId = 1, recv.nodeId = 2
[recv] nodeId = 3, recv.nodeId = 2
I am in Third process
[recv] nodeId = 1, recv.nodeId = 3
[recv] nodeId = 2, recv.nodeId = 3
I am in Fourth process

but,but, if I also put the msgsnd() into another function, it works well again.

comproc.c

typedef struct Msg_context {
    int nodeId;

} Msg_context;

int com_process_send(int nodeId) 
{
    int i = 1;
    for (i = 1; i <= 3; i++) {
        if (i == nodeId) {
            continue;
        }
        int msgid = -1;
        Msg_context msgSend;

        msgid = msgget((key_t)i, 0666 | IPC_CREAT);


        if (msgid == -1) {
            printf("msgid == -1 in %s with nodeId = %d\n", __FUNCTION__, nodeId);
        }
        msgSend.nodeId = nodeId;
        //int length = sizeof(msgSend.nodeId);

        int ret = msgsnd(msgid, (void *)&msgSend, 4, 0);
        if (ret == -1) {
            printf("send message error in %s with nodeId = %d\n", __FUNCTION__, nodeId);
        }

        printf("[send] nodeId = %d, dest msg = %d\n", nodeId, i);

    }
    return 0;
}


int com_process_recv(int nodeId)
{

    int msgrecvId = -1;
    Msg_context msgRecv;
    msgrecvId = msgget((key_t)nodeId, 0666 | IPC_CREAT);


    if (msgrecvId == -1) {
        printf("msgrecvId == -1\n");
    }

    if (msgrcv(msgrecvId, (void *)&msgRecv, BUFSIZ, 0, 0) == -1) {
        printf("send message error\n");
    }
    printf("[recv] nodeId = %d, recv.nodeId = %d\n", nodeId, msgRecv.nodeId);



}

void test2(int nodeId)
{


    com_process_send(nodeId);

    sleep(1);
    while (1) {
        com_process_recv(nodeId);


    }


}

So It is very odd, right? I don't understand why it happened. So I am very hope you guys can help me to understand that. Thank you so much!!!

mHuster
  • 11
  • 1
  • You're running multiple processes all reading from the same message queues. They can run in unpredictable orders, and small changes to the program can affect the timing. – Barmar Jun 01 '18 at 05:41
  • My task is that multiple processes write message to the same message queues, but I just let first process to read from first message queue. second process to read from second message queue. and so on. what should I do? – mHuster Jun 01 '18 at 06:03
  • I see, I misread the code. But there's no way to tell which process is printing each `[recv]` message. Put the process ID in that line. – Barmar Jun 01 '18 at 06:09
  • The first nodeId is process id. because in the first process, I make the nodeId = 1. the second process, nodeId = 2. and so on. – mHuster Jun 01 '18 at 06:36

1 Answers1

0

From what I read in your comments, if you want that different process read only messages addressed to them, you should have a look to the msgtyp arguments of msgrcv()

From man page:

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

The argument msgtyp specifies the type of message requested as follows:

If msgtyp is 0, then the first message in the queue is read.

If msgtyp is greater than 0, then the first message in the queue of type msgtyp is read, unless MSG_EXCEPT was specified in msgflg, in which case the first message in the queue of type not equal to msgtyp will be read.

If msgtyp is less than 0, then the first message in the queue with the lowest type less than or equal to the absolute value of msgtyp will be read.

In your case, calling

    msgrcv(msgrecvId, (void *)&msgRecv, BUFSIZ, 0, nodeId) == -1)

will help you to have 1st process reading from 1st message queue, 2nd process from 2nd msq, etc...

CimCim
  • 48
  • 5
  • Thank you very much! It works. I found I didn't understand the message queue clearly. I know the msgtyp and how it works. But it's affected by the message queue I used earlier. A thread has a message queue. so I think I have four process, it needs four message queues. In fact, it just needs one message queue and use the msgtyp to distinguish it. – mHuster Jun 03 '18 at 13:47
  • @mHuster Yes, you are true; it's not 4 different message queues, it's 4 different message types in the same message queue, with a filter on the type – CimCim Jun 04 '18 at 10:04