gpt4 book ai didi

C - 共享内存 - 共享结构内的动态数组

转载 作者:IT王子 更新时间:2023-10-28 23:31:47 26 4
gpt4 key购买 nike

我正在尝试共享这样的结构
示例:

typedef struct {
int* a;
int b;
int c;
} ex;

在进程之间,问题是当我使用 malloc 初始化“a”时,它对执行此操作的进程的堆来说是私有(private)的(或者至少我认为这是发生的情况)。有没有办法使用这个有效的结构创建共享内存(使用 shmget、shmat)?

编辑:我在 Linux 上工作。
编辑:我有一个像这样初始化缓冲区的过程:

key_t key = ftok("gr", 'p');   
int mid = shmget(key, sizeof(ex), IPC_CREAT | 0666);
ex* e = NULL;
status b_status = init(&e, 8); //init gives initial values to b c and allocate space for 'a' with a malloc
e = (ex*)shmat(mid, NULL, 0);

另一个进程像这样将自己附加到共享内存:

key_t key = ftok("gr", 'p');
int shmid = shmget(key, sizeof(ex), 0);
ex* e;
e = (ex*)shmat(shmid, NULL, 0);

然后从a中获取一个元素,在这种情况下,在位置1

int i = get_el(e, 1);

最佳答案

首先,要共享 int *a 字段指向的内容,您需要复制与其相关的整个内存。因此,您将需要一个至少可以容纳 size_t shm_size = sizeof(struct ex) + get_the_length_of_your_ex(); 的共享内存。

从现在开始,既然你提到了 shmget 和 shmat,我就假设你运行的是 Linux 系统。
第一步是创建共享内存段。如果您可以确定 int *a 内容大小的上限,那将是一件好事。这样您就不必一遍又一遍地创建/删除共享内存段。但是,如果您这样做,则需要额外的开销来说明实际数据需要多长时间。我假设一个简单的 size_t 就可以达到这个目的。

然后,在您创建 segmentation 后,您必须正确设置数据以使其包含您想要的内容。请注意,虽然内存段的物理地址始终相同,但在调用 shmat 时会得到 virtual 指针,这些指针仅在调用 的进程中可用shmat。下面的示例代码应该为您提供一些技巧。

#include <sys/types.h>
#include <sys/ipc.h>

/* Assume a cannot point towards an area larger than 4096 bytes. */
#define A_MAX_SIZE (size_t)4096

struct ex {
int *a;
int b;
int c;
}

int shm_create(void)
{
/*
* If you need to share other structures,
* You'll need to pass the key_t as an argument
*/
key_t k = ftok("/a/path/of/yours");
int shm_id = 0;
if (0 > (shm_id = shmget(
k, sizeof(struct ex) + A_MAX_SIZE + sizeof(size_t), IPC_CREAT|IPC_EXCL|0666))) {
/* An error occurred, add desired error handling. */
}
return shm_id;
}

/*
* Fill the desired shared memory segment with the structure
*/
int shm_fill(int shmid, struct ex *p_ex)
{
void *p = shmat(shmid, NULL, 0);
void *tmp = p;
size_t data_len = get_my_ex_struct_data_len(p_ex);
if ((void*)(-1) == p) {
/* Add desired error handling */
return -1;
}
memcpy(tmp, p_ex, sizeof(struct ex));
tmp += sizeof(struct ex);
memcpy(tmp, &data_len, sizeof(size_t);
tmp += 4;
memcpy(tmp, p_ex->a, data_len);

shmdt(p);
/*
* If you want to keep the reference so that
* When modifying p_ex anywhere, you update the shm content at the same time :
* - Don't call shmdt()
* - Make p_ex->a point towards the good area :
* p_ex->a = p + sizeof(struct ex) + sizeof(size_t);
* Never ever modify a without detaching the shm ...
*/
return 0;
}

/* Get the ex structure from a shm segment */
int shm_get_ex(int shmid, struct ex *p_dst)
{
void *p = shmat(shmid, NULL, SHM_RDONLY);
void *tmp;
size_t data_len = 0;
if ((void*)(-1) == p) {
/* Error ... */
return -1;
}
data_len = *(size_t*)(p + sizeof(struct ex))
if (NULL == (tmp = malloc(data_len))) {
/* No memory ... */
shmdt(p);
return -1;
}
memcpy(p_dst, p, sizeof(struct ex));
memcpy(tmp, (p + sizeof(struct ex) + sizeof(size_t)), data_len);
p_dst->a = tmp;
/*
* If you want to modify "globally" the structure,
* - Change SHM_RDONLY to 0 in the shmat() call
* - Make p_dst->a point to the good offset :
* p_dst->a = p + sizeof(struct ex) + sizeof(size_t);
* - Remove from the code above all the things made with tmp (malloc ...)
*/
return 0;
}

/*
* Detach the given p_ex structure from a shm segment.
* This function is useful only if you use the shm segment
* in the way I described in comment in the other functions.
*/
void shm_detach_struct(struct ex *p_ex)
{
/*
* Here you could :
* - alloc a local pointer
* - copy the shm data into it
* - detach the segment using the current p_ex->a pointer
* - assign your local pointer to p_ex->a
* This would save locally the data stored in the shm at the call
* Or if you're lazy (like me), just detach the pointer and make p_ex->a = NULL;
*/

shmdt(p_ex->a - sizeof(struct ex) - sizeof(size_t));
p_ex->a = NULL;
}

请原谅我的懒惰,它会进行空间优化,以完全不复制 struct exint *a 指针的值,因为它在共享内存,但我为自己节省了额外的代码来处理这个问题(以及一些指针检查,如 p_ex 参数完整性)。

但是当你完成后,你必须找到一种方法在你的进程之间共享 shm ID。这可以使用套接字、管道...或使用具有相同输入的 ftok 来完成。

关于C - 共享内存 - 共享结构内的动态数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14558443/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com