簡體   English   中英

如何正確地將 C 結構寫入磁盤上的文件,以便可以在其上使用 mmap?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM