我尝试通过mmap()
/dev/shm
上的/dev/shm
文件解决此问题,并且可以查询/dev/shm
上的可用空间以确定是否有足够的可用内存(也称为免费{ {1}})可用于下一个mmap()
和/或mremap()
操作。但是,以下示例程序显示mremap()
不可信;它似乎不尊重,例如原始MAP_POPULATE
的初始mmap()
?并mmap()
本身似乎做懒惰的地图人口?至少当我只有8GB RAM可用时,它似乎很愉快(没有错误)mmap()
256GB文件!为什么?也许是因为ftruncate()允许我在/ dev / shm上创建一个256GB的文件,大小只有8GB!为什么呢?
#define _GNU_SOURCE
#include <sys/mman.h>
#include <assert.h>
#include <stdio.h>
#include <stdint.h>
#include <sys/statvfs.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
// $ gcc -o dev-shm dev-shm.c && ./dev-shm
// /dev/shm/ free: 7824 MB, /dev/shm/mytemp.txt size: 1 MB; after ftruncate( 1MB)
// /dev/shm/ free: 7823 MB, /dev/shm/mytemp.txt size: 1 MB; after mmap( 1MB)
// /dev/shm/ free: 7823 MB, /dev/shm/mytemp.txt size: 2 MB; after ftruncate( 2MB)
// /dev/shm/ free: 7822 MB, /dev/shm/mytemp.txt size: 2 MB; after mmap( 2MB)
// /dev/shm/ free: 7822 MB, /dev/shm/mytemp.txt size: 3 MB; after ftruncate( 3MB)
// /dev/shm/ free: 7822 MB, /dev/shm/mytemp.txt size: 3 MB; after mremap( 3MB)
// Question #1: Why does mremap() not reduce /dev/shm free?
//
// /dev/shm/ free: 7824 MB, /dev/shm/mytemp.txt size: 1 MB; after ftruncate( 1MB)
// /dev/shm/ free: 7823 MB, /dev/shm/mytemp.txt size: 1 MB; after mmap( 1MB)
// /dev/shm/ free: 7823 MB, /dev/shm/mytemp.txt size: 2 MB; after ftruncate( 2MB)
// /dev/shm/ free: 7822 MB, /dev/shm/mytemp.txt size: 2 MB; after mmap( 2MB)
// /dev/shm/ free: 7822 MB, /dev/shm/mytemp.txt size: 262144 MB; after ftruncate(262144MB)
// /dev/shm/ free: 7822 MB, /dev/shm/mytemp.txt size: 262144 MB; after mremap(262144MB)
// Question #2: How can a 256GB file exist on /dev/shm?
//
// /dev/shm/ free: 7824 MB, /dev/shm/mytemp.txt size: 1 MB; after ftruncate( 1MB)
// /dev/shm/ free: 7823 MB, /dev/shm/mytemp.txt size: 1 MB; after mmap( 1MB)
// /dev/shm/ free: 7823 MB, /dev/shm/mytemp.txt size: 262144 MB; after ftruncate(262144MB)
// /dev/shm/ free: 0 MB, /dev/shm/mytemp.txt size: 262144 MB; after mmap(262144MB)
// /dev/shm/ free: 0 MB, /dev/shm/mytemp.txt size: 263168 MB; after ftruncate(263168MB)
// /dev/shm/ free: 0 MB, /dev/shm/mytemp.txt size: 263168 MB; after mremap(263168MB)
// Question #3: How can mmap() MAP_POPULATE a 256GB file?
uint64_t get_dev_shm_free(const char * function, uint64_t size_mb) {
struct statvfs mystatvfs; assert(0 == statvfs("/dev/shm/", &mystatvfs));
uint64_t available = mystatvfs.f_bsize * mystatvfs.f_bfree;
struct stat mystat; assert(0 == stat("/dev/shm/mytemp.txt", &mystat));
uint64_t filesize = mystat.st_size;
printf("/dev/shm/ free: %4.0f MB, /dev/shm/mytemp.txt size: %6.0f MB; %s(%6luMB)\n", available / 1024.0 / 1024.0, filesize / 1024.0 / 1024.0, function, size_mb);
return available;
}
void grow_dev_shm_file(uint64_t size_mb_1, uint64_t size_mb_2, uint64_t size_mb_3) {
unlink("/dev/shm/mytemp.txt");
int fd = open("/dev/shm/mytemp.txt", O_RDWR | O_CREAT, 0600); assert(-1 != fd);
int value = ftruncate(fd, size_mb_1 * 1024 * 1024); assert(-1 != value);
get_dev_shm_free("after ftruncate", size_mb_1);
void * mymem = mmap(NULL, size_mb_1 * 1024 * 1024, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NORESERVE | MAP_POPULATE, fd, 0); assert(MAP_FAILED != mymem);
get_dev_shm_free("after mmap", size_mb_1);
close(fd);
fd = open("/dev/shm/mytemp.txt", O_RDWR | O_CREAT, 0600); assert(-1 != fd);
value = ftruncate(fd, size_mb_2 * 1024 * 1024); assert(-1 != value);
get_dev_shm_free("after ftruncate", size_mb_2);
value = munmap(mymem, size_mb_1 * 1024 * 1024); assert(-1 != value);
mymem = mmap(NULL, size_mb_2 * 1024 * 1024, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NORESERVE | MAP_POPULATE, fd, 0); assert(MAP_FAILED != mymem);
get_dev_shm_free("after mmap", size_mb_2);
close(fd);
fd = open("/dev/shm/mytemp.txt", O_RDWR | O_CREAT, 0600); assert(-1 != fd);
value = ftruncate(fd, size_mb_3 * 1024 * 1024); assert(-1 != value);
get_dev_shm_free("after ftruncate", size_mb_3);
mymem = mremap(mymem, size_mb_2 * 1024 * 1024, size_mb_3 * 1024 * 1024, MREMAP_MAYMOVE); assert(MAP_FAILED != mymem);
get_dev_shm_free("after mremap", size_mb_3);
close(fd);
munmap(mymem, size_mb_3 * 1024 * 1024);
unlink("/dev/shm/mytemp.txt");
}
int main(void) {
grow_dev_shm_file(1, 2, 3); printf("Question #1: Why does mremap() not reduce /dev/shm free?\n\n");
grow_dev_shm_file(1, 2, 256 * 1024); printf("Question #2: How can a 256GB file exist on /dev/shm?\n\n");
grow_dev_shm_file(1, 256 * 1024, 257 * 1024); printf("Question #3: How can mmap() MAP_POPULATE a 256GB file?\n\n");
}