PMDK Programming Guidelines
在使用 libpmemobj
库时,不需要直接使用 mmap
。libpmemobj
提供了高级的 API 来管理持久内存池和分配内存。mmap
通常用于更底层的内存映射操作,而 libpmemobj
封装了这些操作,使得管理持久内存更加方便和安全。
libpmemobj 在使用 libpmemobj
库时,不需要直接使用 mmap
。libpmemobj
提供了高级的 API 来管理持久内存池和分配内存。mmap
通常用于更底层的内存映射操作,而 libpmemobj
封装了这些操作,使得管理持久内存更加方便和安全。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include <libpmemobj.h> #include <iostream> #include <cassert> #include <cstring> #include <unistd.h> #include <stdlib.h> #include <stdio.h> void init_pmem () { const char *pool_name = "/mnt/pmem0/matianmao/fast_fair.data" ; const char *layout_name = "fast_fair" ; size_t pool_size = 64LL * 1024 * 1024 * 1024 ; if (access (pool_name, 0 )) { pmem_pool = pmemobj_create (pool_name, layout_name, pool_size, 0666 ); if (pmem_pool == nullptr ) { std::cout << "[FAST FAIR]\tcreate fail\n" ; assert (0 ); } std::cout << "[FAST FAIR]\tcreate\n" ; } else { pmem_pool = pmemobj_open (pool_name, layout_name); std::cout << "[FAST FAIR]\topen\n" ; } std::cout << "[FAST FAIR]\topen pmem pool successfully\n" ; } void *allocate (size_t size) { void *addr; PMEMoid ptr; int ret = pmemobj_zalloc (pmem_pool, &ptr, sizeof (char ) * size, TOID_TYPE_NUM (char )); if (ret) { std::cout << "[FAST FAIR]\tallocate btree successfully\n" ; assert (0 ); } addr = (char *)pmemobj_direct (ptr); return addr; }
1️⃣ 使用 libpmemobj
库函数读写持久内存的示例代码 libpmemobj_pmem.cpp (without mmap —— 封装📦好了):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 #include <libpmemobj.h> #include <iostream> #include <cassert> #include <cstring> #include <unistd.h> #include <stdlib.h> #include <stdio.h> PMEMobjpool *pmem_pool; #define TOID_TYPE_NUM_CHAR 1 void init_pmem () { const char *pool_name = "/mnt/pmem1/libpmemobj_pmem" ; const char *layout_name = "fast_fair" ; size_t pool_size = 16LL * 1024 * 1024 * 1024 ; if (access (pool_name, 0 )) { pmem_pool = pmemobj_create (pool_name, layout_name, pool_size, 0666 ); if (pmem_pool == nullptr ) { std::cout << "[FAST FAIR]\tcreate fail\n" ; assert (0 ); } std::cout << "[FAST FAIR]\tcreate\n" ; } else { pmem_pool = pmemobj_open (pool_name, layout_name); if (pmem_pool == nullptr ) { std::cout << "[FAST FAIR]\topen fail\n" ; assert (0 ); } std::cout << "[FAST FAIR]\topen\n" ; } std::cout << "[FAST FAIR]\topen pmem pool successfully\n" ; } void *allocate (size_t size) { void *addr; PMEMoid ptr; int ret = pmemobj_zalloc (pmem_pool, &ptr, sizeof (char ) * size, TOID_TYPE_NUM_CHAR); if (ret) { std::cout << "[FAST FAIR]\tallocate fail\n" ; assert (0 ); } addr = pmemobj_direct (ptr); return addr; } int main () { init_pmem (); void *pmem_addr = allocate (1024 ); std::cout << "[FAST FAIR]\tallocated 1024 bytes at " << pmem_addr << "\n" ; strcpy ((char *)pmem_addr, "Hello, Persistent Memory!" ); std::cout << "[FAST FAIR]\tdata written: " << (char *)pmem_addr << "\n" ; pmemobj_close (pmem_pool); std::cout << "[FAST FAIR]\tpmem pool closed\n" ; return 0 ; }
编译命令:
1 2 $ g++ -o libpmemobj libpmemobj_pmem.cpp -lpmemobj $ ./libpmemobj
mmap 2️⃣ 如果不使用 libpmemobj
库函数来读写持久内存(PM),你可以直接使用 mmap
函数将持久内存映射到虚拟地址空间,然后通过指针操作进行读写。以下是一个示例代码 mmap_pmem.cpp ,展示了如何使用 mmap
来读写持久内存:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 #include <fcntl.h> #include <sys/mman.h> #include <unistd.h> #include <iostream> #include <cstring> #include <cassert> #define PMEM_FILE_PATH "/mnt/pmem1/mmap_pmem" #define PMEM_FILE_SIZE (16LL * 1024 * 1024 * 1024) void * pmem_addr = nullptr ;int pmem_fd = -1 ;void init_pmem () { pmem_fd = open (PMEM_FILE_PATH, O_RDWR | O_CREAT, 0666 ); if (pmem_fd < 0 ) { std::cerr << "Failed to open or create PMEM file" << std::endl; exit (1 ); } if (ftruncate (pmem_fd, PMEM_FILE_SIZE) != 0 ) { std::cerr << "Failed to set PMEM file size" << std::endl; close (pmem_fd); exit (1 ); } pmem_addr = mmap (nullptr , PMEM_FILE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, pmem_fd, 0 ); if (pmem_addr == MAP_FAILED) { std::cerr << "Failed to mmap PMEM file" << std::endl; close (pmem_fd); exit (1 ); } std::cout << "PMEM initialized successfully" << std::endl; } void close_pmem () { if (pmem_addr != nullptr ) { munmap (pmem_addr, PMEM_FILE_SIZE); pmem_addr = nullptr ; } if (pmem_fd >= 0 ) { close (pmem_fd); pmem_fd = -1 ; } std::cout << "PMEM closed successfully" << std::endl; } int main () { init_pmem (); void * data_addr = static_cast <char *>(pmem_addr) + 1024 ; std::cout << "Allocated 1024 bytes at " << data_addr << std::endl; strcpy (static_cast <char *>(data_addr), "Hello, Persistent Memory!" ); std::cout << "Data written: " << static_cast <char *>(data_addr) << std::endl; close_pmem (); return 0 ; }
pmem_map_file 3️⃣ 调用 pmem_map_file
函数来映射 PM,pmem_map_file
是 libpmem
库中的一个函数,用于将持久内存文件映射到虚拟地址空间。示例代码 pmem.c 如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 #include <fcntl.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <libpmem.h> #include <stdio.h> #include <stdlib.h> #define PMEM_SIZE 1024 #define PMEM_FILE "/mnt/pmem1/pmem_file" int main () { int fd = open (PMEM_FILE, O_RDWR | O_CREAT | O_TRUNC, 0666 ); if (fd < 0 ) { perror ("open" ); return EXIT_FAILURE; } ftruncate (fd, PMEM_SIZE); void *pmem_addr = pmem_map_file (PMEM_FILE, PMEM_SIZE, PMEM_FILE_CREATE, 0666 , NULL , NULL ); if (pmem_addr == NULL ) { perror ("pmem_map_file" ); return EXIT_FAILURE; } sprintf (pmem_addr, "Hello, Persistent Memory!" ); pmem_persist (pmem_addr, PMEM_SIZE); printf ("%s\n" , (char *)pmem_addr); pmem_unmap (pmem_addr, PMEM_SIZE); close (fd); return EXIT_SUCCESS; }
pmem_map_file
底层封装的也是 mmap
,以下是 pmem_map_file
实现的一个简化示例,具体实现可能会有所不同:
pmdk/src/libpmem/pmem.c 代码库中对 pmem_map_file
的定义 – create or open the file and map it to memory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #include <libpmem.h> #include <sys/mman.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> void *pmem_map_file (const char *path, size_t len, int flags, mode_t mode, size_t *mapped_lenp, int *is_pmemp) { int fd = open (path, flags, mode); if (fd < 0 ) { perror ("open" ); return NULL ; } if (len == 0 ) { len = lseek (fd, 0 , SEEK_END); if (len == (size_t )-1 ) { perror ("lseek" ); close (fd); return NULL ; } } void *addr = mmap (NULL , len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 ); if (addr == MAP_FAILED) { perror ("mmap" ); close (fd); return NULL ; } close (fd); if (mapped_lenp) *mapped_lenp = len; if (is_pmemp) *is_pmemp = 1 ; return addr; }