在 C 中使用共享内存的 IPC

Posted

技术标签:

【中文标题】在 C 中使用共享内存的 IPC【英文标题】:IPC using shared memory in C 【发布时间】:2014-03-31 11:15:51 【问题描述】:

我正在使用 C linux 中的共享内存实现 IPC。这是我的接收过程。它正在接收正确的长度,但不是消息。但是发送过程正在正确发送它。 请查看此内容并让我知道错误。

//header files
#include "/home/user/msgbuf.h"
#define SHMSZ    127
int main()

    int shmid;
    key_t key;
    message_buf *rbuf;
    rbuf=malloc(sizeof(*rbuf));
    key = ftok("/home/user/shmem",17);

    if ((shmid = shmget(key, SHMSZ, 0666)) < 0)
           perror("shmget");
            exit(1);
    
    printf("\nShared Memory Id = %d\n",shmid);
    if ((rbuf = shmat(shmid, NULL, 0)) == (message_buf *) -1)
           perror("shmat");
            exit(1);
    
    printf("\nMEMORY SEGMENT ATTACHED TO THE CLIENT'S PROCESS\n");

/* Now read what the server put in the memory */
    printf("\nmsglen = %d",rbuf->msglen);  //this is correct
    rbuf->cp=malloc(rbuf->msglen);
    memcpy(&rbuf->cp,rbuf+sizeof(int),sizeof(*rbuf));
    printf("\nMESSAGE :: %s",rbuf->cp); //MESSAGE :: null
    fflush(stdout);
    shmdt(&shmid);
    printf("\nMEMORY SEGMENT %d DETACHED\n",shmid);
    return 0;

msgbuf.h 是

typedef struct msgbuf1

    int msglen;
    char *cp;
message_buf;

谢谢:)

【问题讨论】:

Deer Ghost-downvoter:解释原因。 这是做什么的:memcpy(&amp;rbuf-&gt;cp,rbuf+sizeof(int),rbuf-&gt;msglen); ?您的服务器将您想要接收的消息放在哪里? (m = shmat(shmid, NULL, 0)) == (message_buf *) -1 其中 m 是指向 msg_buf 的指针。然后 m->cp="用户输入的消息"。此外,我已将 rbuf->msglen 更改为 sizeof(*rbuf) 以将 ptr 更改为 cp。 @user3392539 您在rbuf-&gt;cp=malloc(rbuf-&gt;msglen); 中覆盖了cp,所以您肯定不能指望该指针再包含该消息。此外,指针对于进程来说是本地的,不能跨共享内存传输指针,因为指针只在创建它的进程中有效。 【参考方案1】:

您从共享内存区域读取了一个 char*。但是,这指向在远程进程中使用 malloc 分配的缓冲区。因此,它指向该 other 进程的本地进程堆。

这只是未定义的行为。

相反,让字符缓冲区成为共享内存数据结构的一部分:

//header files
#define MAX_SH_BUFSIZE 1024
//
typedef struct msgbuf1

    int msglen;
    char cp[MAX_SH_BUFSIZE];
 message_buf;

【讨论】:

我不能让它动态化吗?我的意思是使用 *cp 而不是字符数组。这就是我在上面的 prog 中使用 memcpy 的原因 没有。正如他所说,malloc 返回的缓冲区是调用它的进程私有的。 @JonathonReinhart 对我来说这没有多大意义。为什么他要共享不指向同一进程空间的不透明指针?此外,他在这些东西上调用 memcpy。因此,要么是这个(正如我在回答中所描述的),要么 OP 对结构布局是什么以及 cp 成员的功能完全感到困惑。越看代码我觉得都是 对不起,我实际上是在回复该评论中的 OP。 是的。您的结构恰好包含两个元素:msglencp,它们的值将实际位于该段中。但是,cp 指向该区域之外的地址。当然,我们看不到代码的“服务器”端,因此您完全存储其他内容是“可能的”,但char* 建议cp 旨在包含一个指向字符的 指针。所以你的问题是你有 两个 指针,而你只处理一个)【参考方案2】:

问题出在 malloc 上。 malloc 地址有范围,直到他处理不是共享内存。您不应该在共享内存中使用 malloc。

方法一。

改为使用固定大小的字符数组,如下所示:

typedef struct msgbuf1

    int msglen;
    char cp[MESSAGE_SIZE];
message_buf;

将 MESSAGE_SIZE 设置为您需要的最大数据大小。

方法二。 创建足够大的共享内存。 让您拥有自己的 malloc 和 free 函数,这些函数将在需要时从共享内存中提供内存。 为此,您需要跟踪空闲列表,该列表将空闲内存空间存储在共享内存中。

您可以将共享内存分成 256 字节、512 字节和 1024 字节之类的块。 现在,当您需要内存时,共享内存的自定义 malloc 函数应该包含有效提供内存的逻辑。

自定义释放函数将释放程序释放的共享内存,并将该块添加到空闲列表中

【讨论】:

以上是关于在 C 中使用共享内存的 IPC的主要内容,如果未能解决你的问题,请参考以下文章

通过共享内存和管道的 IPC 给出分段错误:C 中的 11

linux进程间的通信(C): 共享内存

UNIX C XSI_IPC对象共享内存

linux c编程:Posix共享内存区

IPC:共享内存终止进程通知

共享内存是最快的一种IPC方式