c ++ msgsnd和msgrvc陷入困境

时间:2016-04-24 13:11:44

标签: c++ linux fork message-queue

我有一个小型的C ++程序,其中主要过程是"创建数据"并将它们发送到应该读取该数据的子(fork)进程。我的问题是,在学校我的代码运行良好,但在我自己的笔记本电脑上,这两个进程在程序启动后就会卡住。具体来说,他们都在等待频道" do_msgrcv"。

这是我的代码:

#define VYROBA 1    // Manufacturer
#define PREPRAVA 2  // Transport

void manufacturer ( ) {
    static int count = 0;
    int rcv [ 2 ];

    while ( 1 ) {
        int snd [ 2 ] = { VYROBA, count };

        int ret = msgsnd ( glb_msg_id, &snd, sizeof ( int ), 0 );
        ret =  msgrcv ( glb_msg_id, &rcv, sizeof ( int ), PREPRAVA, 0 );
        printf ( "Got crate\n" );
    }
}

void consumer ( ) {
    static int count = 0;
    int rcv [ 2 ];

    while ( 1 ) {
        int ret = msgrcv ( glb_msg_id, &rcv, sizeof ( int ), VYROBA, 0 );
        usleep ( 500000 );
        if ( ret < 0 ) {
            printf ( "Can't read message.\n" );
        }

        printf ( "Got product: %d\r\n", rcv [ 1 ] );
        fflush ( stdout );

        rcv [ 1 ]++;

        if ( rcv [ 1 ] == 10 ) {
            int snd [ 2 ] = { PREPRAVA, rcv [ 1 ] };
            ret = msgsnd ( glb_msg_id, &snd, sizeof ( int ), 0 );
        } else {
            ret = msgsnd ( glb_msg_id, &rcv, sizeof ( int ), 0 );
        }
    }
}

如果它在学校有用,我们有Ubuntu 12.04,我使用的是Ubuntu 16.04。

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

您使用的是Linux内核since version 2.6支持的系统V消息队列,因此您考虑的是Ubuntu版本。

现在,如果您查看手册,msgrcv() and msgsnd()使用消息缓冲区,则hwich应具有以下结构:

endIf

一旦你开始不使用这个结构而是一些手动管理的缓冲区,你就有可能获得不可移植的代码(例如,你必须确保正确的大小和填充,考虑到字节顺序等... )。这肯定是这里发生的事情。

消息结构以编码为struct msgbuf { long mtype; /* message type, must be > 0 */ char mtext[1]; /* message data */ }; 的消息类型开头,您假设它与long(数组的第一个元素)相同。但是C ++标准并未修复intint的大小(仅限其最小大小):此大小可能为vary between platforms, compilers and CPU architecture。例如:

  • 如果在大学时你运行Ubuntu 32位,longint都是32位且大小相同。你的代码有效。
  • 如果你在家里运行Ubuntu 64位,你的long将是64位,而long仍然是32位。所以你的缓冲区太短,导致intmsgsnd()覆盖缓冲区。这将是未定义的行为,而不是消息类型将被破坏的事实。

我认为更改代码并使用正确的缓冲区结构可以解决问题。

补充说明

顺便说一下,你的分支逻辑使制造商()执行两次:在原始过程中,但也在消费者完成后分叉的那些!

msgrcv()

最好使用if ( !fork ( ) ) { consumer ( ); } manufacturer ( ); 来确保它仅在应有的位置使用。