![](/img/trans.png)
[英]How to use pthread in C to prevent simultaneous read and write to a file on disk?
[英]How to properly write C structure to file on disk, so it was possible to use mmap on it?
我在 memory 中使用以下 C 结构:
typedef struct MyStructHdr
{
char text[4];
int version_num;
uint64 init_value;
uint64 entries[];
} MyStructHdr;
typedef MyStructHdr *MyStruct;
Field entries[]
是指向某个灵活数组的指针。 类型uint64
是一种自定义的可移植应用程序特定类型,它在 32 位操作系统上添加了uint64_t
支持。
我必须正确地将此结构写入文件,以便以后能够在其上使用mmap()
(在同一平台/操作系统上):
map = (MyStruct) mmap(NULL, MyStructActualSize,
PROT_READ | PROT_WRITE, MAP_SHARED,
mystruct_fd, 0);
我现在应该做什么? 我只是使用write()
一个一个地写入MyStruct
字段(并通过缓冲区按块写入entries[]
)。 最后写入CRC32
校验和。
在我可用的所有 64 位系统上一切正常。 似乎前 4 个字符 + 32 位int
对齐到单个 64 位块中,并且uint64
简单地扩展为uint64_t
,所以在写入后一切都正确地被mmap
了。
但是,恐怕在 32 位系统或某些特定的操作系统/体系结构上,应用了不同的 alignment 规则并且没有uint64_t
并且uint64
扩展为:
{
int val1;
unsigned long int val2;
}
写后我会得到不正确的mmap
。
将这样的结构写入文件并在此之后使用mmap
的可移植方式是什么?
PS 实际上,这都是关于 PostgreSQL 扩展和uint64
这里是pg_atomic_uint64
,但我认为这个问题更笼统。
您不应该一个一个地写成员,因为这不会考虑成员之间的填充。 一次性写下全部内容:
write(fd, MyStruct, sizeof(MyStructHdr) + entry_count * sizeof(uint64));
其中entry_count
是灵活数组成员中的元素数。
如果您需要单独编写每个成员以实现原子性,您可以使用offsetof
宏来获取包含填充在内的大小。
write(fd, &MyStruct->text, offsetof(MyStructHdr, version_num));
write(fd, &Mystruct->version_num, offsetof(MyStructHdr, init_value) - offsetof(MyStructHdr, version_num));
write(fd, &MyStruct->init_value, offsetof(MyStructHdr, entries) - offsetof(MyStructHdr, init_value));
然后分块写入MyStruct->entries
数组。 您无需担心那里的填充,因为数组元素上的sizeof
包括元素之间的填充(这确保sizeof array == element_count * sizeof array[0]
);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.