gpt4 book ai didi

c - Linux中共享内存中的多个链接列表

转载 作者:IT王子 更新时间:2023-10-29 01:27:25 26 4
gpt4 key购买 nike

我正在使用C语言和Linux作为平台。我想在多个进程中共享多个结构,这些结构有链接列表的头部(这些列表也应该共享)和指向彼此的指针。此数据所需的内存可达 1Mb。因为我不能在共享内存中使用指针,因为它们对不同的进程无效。

有两种选择:1)要么使用偏移值而不是指针。2) 否则,使用不同的共享内存并使用共享内存 ID(由 shmget 返回)而不是指针。

由于要共享的内存很大,哪个选项更好?你能建议另一种选择吗?

谢谢。

最佳答案

使用偏移值。

使用从共享内存区域开始的 size_t 偏移量(以字符为单位)代替指针。您将需要在访问或操作这些列表的任何地方执行此操作。

编辑添加:

以这种方式使用偏移量可以在大多数体系结构上编译为非常高效的代码,并且您可以使用 __sync..()内置函数以原子方式访问和修改它们。请记住对所有 访问使用内置函数,包括读取:否则值可能在非原子读取期间被原子修改(反之亦然),从而导致数据损坏。

如果您知道共享内存的大小永远不会超过 4GB,那么您可以使用 uint32_t 作为偏移量类型,在 64 位架构上每个“指针”节省四个字节。如果将所有目标对齐到 32 位边界,则可以将其翻两番,达到 8GB。

使用 uint32_t 的一个非常好的副作用是你可以在所有 64 位和一些 32 位上自动操作指针对(两个连续的偏移量)架构。假设共享内存中的所有内容也与 32 位边界对齐,并使用每个 32 位单元的偏移量,您可以使用原子方式获取/设置指针对

static inline void get_pair(void *const base, const uint32_t offset, uint32_t *const pair)
{
uint64_t *const ptr = (uint64_t *)(offset + (uint32_t *)base);
uint64_t val;

val = __sync_or_and_fetch(ptr, (uint64_t)0);

memcpy(pair, &val, sizeof val);
}

static inline void switch_pair(void *const base, const uint32_t offset, const uint32_t *const new, uint32_t *const old)
{
uint64_t *const ptr = (uint64_t *)(offset + (uint32_t *)base);
uint64_t oldval, newval;

memcpy(newval, &new, sizeof newval);

do {
/* Note: this access does not need to be atomic, */
memcpy(oldval, ptr, sizeof oldval);
/* because the next one verifies it. */
} while (!__sync_bool_compare_and_swap(ptr, oldval, newval));

if (old)
memcpy(old, &oldval, sizeof oldval);
}

__sync...() 内置函数至少在 GCC 和 Intel CC 中有效。新的 C11 标准也采用了 C++11 风格 __atomic..()内置,但要在当前编译器中实现这些功能还需要一些时间。

如果您编写库代码,或者您希望维护数年的代码,它可能会节省您查找两种内置类型的时间,并为您自己(或任何将要维护它的人)添加注释是时候在内置函数之间进行转换了),以描述您将使用哪个原子内置函数(如果它们已经可用)。

最后,请记住,像这样使用共享内存意味着您必须遵守与多个线程并发访问内存相同的注意事项。原子操作会有所帮助,如果您可以原子操作指针对,您可以使用列表执行一些非常聪明的技巧,但您仍然需要非常敏锐地了解极端情况和可能的竞争条件。

关于c - Linux中共享内存中的多个链接列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13155446/

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