IPC消息队列不适用于分叉进程

IPC消息队列不适用于分叉进程,c,fork,ipc,C,Fork,Ipc,我尝试将IPC消息队列与分叉进程一起使用,传递指向动态分配字符串的指针,但它不起作用 这是我做的一个简单的测试。它不会打印从队列接收的字符串。但是,如果我尝试删除fork(),它将非常有效 #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <stdio.h> #include <stdlib.h> #include <string.h

我尝试将IPC消息队列与分叉进程一起使用,传递指向动态分配字符串的指针,但它不起作用

这是我做的一个简单的测试。它不会打印从队列接收的字符串。但是,如果我尝试删除
fork()
,它将非常有效

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MSGSZ     128

typedef struct msgbuf {
    long    mtype;
    char    *mtext;
} message_buf;

int
main ()
{
    int msqid;
    char *p;
    key_t key = 129;

    message_buf sbuf, rbuf;
    p = (char *) malloc(sizeof(char) * MSGSZ);

    if ((msqid = msgget(key, IPC_CREAT|0666)) < 0) {
        perror("msgget");
        exit(1);
    }

    if (fork() == 0) {
        strcpy(p, "Did you get this?");
        sbuf.mtype = 1;
        sbuf.mtext = p;

        if (msgsnd(msqid, &sbuf, MSGSZ, IPC_NOWAIT) < 0) {
            perror("msgsnd");
            exit(1);
        }
    }
    else {
        sleep(1);

        if (msgrcv(msqid, &rbuf, MSGSZ, 0, 0) < 0) {
            perror("msgrcv");
            exit(1);
        }

        printf("Forked version: %s\n", rbuf.mtext);
        msgctl(msqid, IPC_RMID, NULL);
    }
}
#包括
#包括
#包括
#包括
#包括
#包括
#定义MSGSZ 128
类型定义结构msgbuf{
长型;
字符*多行文字;
}信息;
int
主要()
{
int msqid;
char*p;
键=129;
信息_buf sbuf,rbuf;
p=(char*)malloc(sizeof(char)*MSGSZ);
如果((msqid=msgget(键,IPC|u CREAT | 0666))<0){
佩罗尔(“msgget”);
出口(1);
}
如果(fork()==0){
strcpy(p,“你收到这个了吗?”);
sbuf.mtype=1;
sbuf.mtext=p;
如果(msgsnd(msqid和sbuf、MSGSZ、IPC_NOWAIT)<0){
perror(“msgsnd”);
出口(1);
}
}
否则{
睡眠(1);
如果(msgrcv(msqid和rbuf,MSGSZ,0,0)<0){
perror(“msgrcv”);
出口(1);
}
printf(“分叉版本:%s\n”,rbuf.mtext);
msgctl(msqid,IPC_RMID,NULL);
}
}

问题是您正在跨进程边界发送指针。指针仅在同一进程内有效,在另一进程中发送/使用时没有意义。事实上,您发送的是指针值后跟一大堆垃圾字节,因为
msgbuf.mtext
的大小实际上不是
MSGSZ
字节(因此技术上调用未定义的行为)

您需要做的是在消息中内联声明缓冲区。也就是说,将
消息的定义更改为:

typedef struct msgbuf {
    long    mtype;
    char    mtext[MSGSZ];
} message_buf;
然后直接压缩到
多行文字

strcpy(sbuf.mtext, "Did you get this?");
为清楚起见,以下是完整的程序及其所描述的更改:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MSGSZ     128

typedef struct msgbuf {
    long    mtype;
    char    mtext[MSGSZ];
} message_buf;

int
main (void)
{
    int msqid;
    key_t key = 129;

    message_buf sbuf, rbuf;

    if ((msqid = msgget(key, IPC_CREAT|0666)) < 0) {
        perror("msgget");
        exit(1);
    }

    if (fork() == 0) {
        strcpy(sbuf.mtext, "Did you get this?");
        sbuf.mtype = 1;

        if (msgsnd(msqid, &sbuf, MSGSZ, IPC_NOWAIT) < 0) {
            perror("msgsnd");
            exit(1);
        }
    }
    else {
        sleep(1);

        if (msgrcv(msqid, &rbuf, MSGSZ, 0, 0) < 0) {
            perror("msgrcv");
            exit(1);
        }

        printf("Forked version: %s\n", rbuf.mtext);
        msgctl(msqid, IPC_RMID, NULL);
    }
}
#包括
#包括
#包括
#包括
#包括
#包括
#定义MSGSZ 128
类型定义结构msgbuf{
长型;
字符多行文字[MSGSZ];
}信息;
int
主(空)
{
int msqid;
键=129;
信息_buf sbuf,rbuf;
如果((msqid=msgget(键,IPC|u CREAT | 0666))<0){
佩罗尔(“msgget”);
出口(1);
}
如果(fork()==0){
strcpy(sbuf.mtext,“你收到这个了吗?”);
sbuf.mtype=1;
如果(msgsnd(msqid和sbuf、MSGSZ、IPC_NOWAIT)<0){
perror(“msgsnd”);
出口(1);
}
}
否则{
睡眠(1);
如果(msgrcv(msqid和rbuf,MSGSZ,0,0)<0){
perror(“msgrcv”);
出口(1);
}
printf(“分叉版本:%s\n”,rbuf.mtext);
msgctl(msqid,IPC_RMID,NULL);
}
}