在 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(&rbuf->cp,rbuf+sizeof(int),rbuf->msglen);
?您的服务器将您想要接收的消息放在哪里?
(m = shmat(shmid, NULL, 0)) == (message_buf *) -1 其中 m 是指向 msg_buf 的指针。然后 m->cp="用户输入的消息"。此外,我已将 rbuf->msglen 更改为 sizeof(*rbuf) 以将 ptr 更改为 cp。
@user3392539 您在rbuf->cp=malloc(rbuf->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。
是的。您的结构恰好包含两个元素:msglen
和 cp
,它们的值将实际位于该段中。但是,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的主要内容,如果未能解决你的问题,请参考以下文章