pointers - 具有指针的共享内存数据结构
问题描述
您好我正在尝试使用共享内存 IPC 在进程之间进行通信。但是,当我尝试使用 shmat 来分配指向数据结构的指针时,它会返回共享内存地址的起始地址。我的代码如下
#define SHM_SIZE 10240
struct myds {
int ind;
char *data[1];
};
int main()
{
key_t key = ftok("shmfile",65);
struct myds *nums;
int shmid = shmget(key,SHM_SIZE,0666|IPC_CREAT);
char *shm_addr = (char*) shmat(shmid,(void*)0,0);
int *count = (int *) shm_addr;
*count = 5;
nums = (struct myds *)((void *)shm_addr + sizeof(int));
for(int i = 0; i < *count; i++) {
nums[i].ind = i;
}
char *t = (char*) shmat(shmid,(void*)0,0);
printf("%d\n", *count);
sprintf(t, "check- 112\0");
nums[0].data[0] = t;
printf("Data written in memory:");
getc(stdin);
printf("%d\n", *count);
shmdt(shm_addr);
shmctl(shmid,IPC_RMID,NULL);
return 0;
}
*count 的最后一次打印应该打印 5,而是打印一些不同且非常大的值。这似乎是 sprintf(t, "check-112\0") 的效果。我在这里做错了吗?
解决方案
count
并t
指向相同的内存地址。当sprintf()
通过 向该地址写入新数据时t
,它会覆盖正在通过 读取的值*count
。这就是为什么你会从*count
after中得到垃圾sprintf()
。
看起来您正在尝试将sprintf()
数据写入 指向的内存nums[0].data[0]
,但实际上您并没有设置data[0]
指向任何有意义的地方。返回的起始地址shmat()
是错误的存储地址data[0]
。
由于您正在分配一个非常大的内存块,比myds
实际需要的 5 个结构的数组要多得多,因此您可以指向数组data[0]
中最后分配myds
的结构之后的内存。
尝试更多类似的东西:
#define SHM_COUNT 5
struct myds {
int ind;
char* data[1];
};
int main()
{
key_t key = ftok("shmfile",65);
struct myds *nums;
int shmid = shmget(key, sizeof(int) + (sizeof(struct myds) * SHM_COUNT) + 11, 0666|IPC_CREAT);
char *shm_addr = (char*) shmat(shmid, NULL, 0);
int *count = (int *) shm_addr;
*count = SHM_COUNT;
nums = (struct myds *)(shm_addr + sizeof(int));
for(int i = 0; i < SHM_COUNT; i++) {
nums[i].ind = i;
}
char *t = (char*) (nums + SHM_COUNT);
printf("%d\n", *count);
sprintf(t, "check- 112\0");
for(int i = 0; i < SHM_COUNT; i++) {
nums[i].data[0] = t;
}
printf("Data written in memory:");
getc(stdin);
printf("%d\n", *count);
shmdt(shm_addr);
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
然后其他进程可以简单地使用char*
存储在其中的指针nums[i].data[0]
来访问每个nums[]
元素的字符串。
如果您想为每个nums[]
元素添加不同的字符串,只需分配足够的共享内存来保存所有字符串,然后nums[i].data[0]
在该内存中相应地指向。
更新:如果存储char*
指针对您不起作用,则改为存储偏移量,例如:
#define SHM_COUNT 5
struct myds {
int ind;
size_t data_offset[1];
};
int main()
{
key_t key = ftok("shmfile",65);
struct myds *nums;
int shmid = shmget(key, sizeof(int) + (sizeof(struct myds) * SHM_COUNT) + 11, 0666|IPC_CREAT);
char *shm_addr = (char*) shmat(shmid, NULL, 0);
int *count = (int *) shm_addr;
*count = SHM_COUNT;
nums = (struct myds *)(shm_addr + sizeof(int));
for(int i = 0; i < SHM_COUNT; i++) {
nums[i].ind = i;
}
char *t = (char*) (nums + SHM_COUNT);
printf("%d\n", *count);
sprintf(t, "check- 112\0");
for(int i = 0; i < SHM_COUNT; i++) {
nums[0].data_offset[0] = (t - shm_addr);
}
printf("Data written in memory:");
getc(stdin);
printf("%d\n", *count);
shmdt(shm_addr);
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
然后其他进程可以简单地添加nums[i].data_offset[0]
到它们的本地shm_addr
地址以访问每个nums[]
元素的字符串。
推荐阅读
- redux - 为什么组件没有连接到 redux 商店?
- python - 如何从javascript代码中提取字符串?
- kubernetes - Calico CNI pod 网络无法跨 EKS Kubernetes 工作节点上的不同主机工作
- java - 应该包含/导入什么来识别我的 spark -java 代码中的“$”操作连接功能?
- c# - 使用 Interop.Access 在 Access 中获取页眉和页脚的文本
- docker - 在本地使用 gitlab-runner 并从上一步传递工件
- laravel - React Native 和 Laravel API
- python - 如何减少 Tensorlfow/Keras 使用的 CPU 数量?
- flutter - BottomNavigationBar 颜色错误更改
- python - 将两个 16 位寄存器组合成一个 32 位浮点数