[英]memset large memory region allocated by shm_open/ftruncate/mmap crashes with bus error
我有一个演示程序,它使用shm_open/ftruncate/mmap
来分配 memory:
#include <unistd.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
void shm_alloc(const char* path, size_t size) {
int shmfd = shm_open(path, O_CREAT | O_EXCL | O_TRUNC | O_RDWR, 0666);
if (shmfd == -1) {
perror("shm_open");
exit(1);
}
printf("shm_open success, path: %s, fd: %d\n", path, shmfd);
int ret = ftruncate(shmfd, size);
if (ret != 0) {
perror("ftruncate");
exit(1);
}
printf("ftruncate success, fd: %d, size: %#lx\n", shmfd, size);
void* addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0);
if (addr == MAP_FAILED) {
perror("mmap");
exit(1);
}
printf("mmap success, fd: %d, size: %#lx, addr: %p\n", shmfd, size, addr);
close(shmfd);
memset(addr, 0x00, size); // <===== Crashes here
printf("memset success, size: %#lx, addr: %p\n", size, addr);
}
int main() {
shm_alloc("/a", 0x100000000); // 4GB
shm_alloc("/b", 0x100000000); // 4GB, crashes at the `memset` in this call
return 0;
}
该程序创建两个 4GB 共享 memory 区域并memset
它们。 运行它输出以下内容的程序,然后崩溃:
shm_open success, path: /a, fd: 3
ftruncate success, fd: 3, size: 0x100000000
mmap success, fd: 3, size: 0x100000000, addr: 0x7f4c15625000
memset success, size: 0x100000000, addr: 0x7f4c15625000
shm_open success, path: /b, fd: 3
ftruncate success, fd: 3, size: 0x100000000
mmap success, fd: 3, size: 0x100000000, addr: 0x7f4b15625000
[1] 1250849 bus error (core dumped) ./a.out
如您所见,第一个memset
成功,第二个崩溃,我gdb
编辑了程序,它显示第二个区域mmap
ed 在0x7f4b15625000
没有足够的空间(4GB)(执行p (char*)addr + 0xFFFFFFFF
in ZCA3E1C20EFD5690F97AZA9产生Cannot access memory
错误),但它的空间确实小于 4GB(可能是 2GB 或 3GB,我没有测试准确的大小) 。
我在 Debian 9 上运行,物理 memory 是 16GB,没有交换空间,所以这似乎不是内存不足的问题,有人知道吗? 我不应该相信ftruncate/mmap
调用吗?
编辑:运行df -h
显示/dev/shm
的大小为 7.8G,因此它可能是根本原因。 但是,即使/dev/shm
没有足够的空间,为什么ftruncate
会成功? 为什么当我ls -alh /dev/shm
时,它显示两个文件“a”和“b”,大小均为 4.0GB?
free -h
的 Output :
# before running the program:
total used free shared buff/cache available
Mem: 15G 701M 9.0G 161M 5.7G 14G
Swap: 0B 0B 0B
# after running the program:
total used free shared buff/cache available
Mem: 15G 702M 1.4G 7.8G 13G 6.6G
Swap: 0B 0B 0B
ulimit -a
的 Output :
-t: cpu time (seconds) unlimited
-f: file size (blocks) unlimited
-d: data seg size (kbytes) unlimited
-s: stack size (kbytes) 8192
-c: core file size (blocks) unlimited
-m: resident set size (kbytes) unlimited
-u: processes 65535
-n: file descriptors 1024768
-l: locked-in-memory size (kbytes) 64
-v: address space (kbytes) unlimited
-x: file locks unlimited
-i: pending signals 63053
-q: bytes in POSIX msg queues 819200
-e: max nice 0
-r: max rt priority 0
-N 15: unlimited
我使用 16GB Ubuntu VM 重现了这个问题,默认情况下 /dev/shm 也有 8 GB。
将/dev/shm
增加到 9GB 后,它可以工作:
$ ./tm
shm_open success, path: /a, fd: 3
ftruncate success, fd: 3, size: 0x100000000
mmap success, fd: 3, size: 0x100000000, addr: 0x7ff849486000
memset success, size: 0x100000000, addr: 0x7ff849486000
shm_open success, path: /b, fd: 3
ftruncate success, fd: 3, size: 0x100000000
mmap success, fd: 3, size: 0x100000000, addr: 0x7ff749486000
memset success, size: 0x100000000, addr: 0x7ff749486000
$ df /dev/shm -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 9.0G 8.1G 1.0G 89% /dev/shm
$
我无法回答有关 /dev/shm 中的 ftruncate 和文件大小的问题,但它可以工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.