madvise(*, *, MADV_DONTNEED)
应该纯粹是建议性的吗?我尝试扫描 /proc/self/maps
并致电 madvise(addr, size, MADV_DONTNEED)
:
#include <stdio.h>
#include <sys/mman.h>
int main(void) {
FILE *fp;
char line[1024];
fp = fopen("/proc/self/maps", "r");
if (fp == NULL) {
perror("Failed to open maps file");
return 1;
}
while (fgets(line, sizeof(line), fp)) {
char addr[32], perms[8], offset[32], dev[32], inode[32], path[256];
unsigned long start, end;
path[0] = '\0';
sscanf(line, "%lx-%lx %s %s %s %s %[^\n]", &start, &end, perms, offset, dev, inode, path);
int ret = madvise((void*)start, end - start, MADV_DONTNEED);
if(ret == 0)
printf(" OK\n");
else
printf(" Error\n");
fflush(stdout);
}
fclose(fp);
}
但是这会打印:
OK
OK
OK
OK
Segmentation fault
有没有一种简单的方法来告诉(从
/proc/self/maps
、/proc/self/smaps
或其他方式)进程允许在哪些内存段上调用 madvise(*, *, MADV_DONTNEED)
?
man 2 madvise
说:
这些建议值不会影响应用程序的语义(MADV_DONTNEED 情况除外),但可能会影响其性能。
并且:
MADV_DONTNEED 操作成功后,指定区域中的内存访问语义将发生更改:该范围内页面的后续访问将成功,但会导致从底层映射的最新内容重新填充内存内容文件(用于共享文件映射、共享匿名映射和基于 shmem 的技术,例如 System V 共享内存段)或用于匿名私有映射的按需零填充页面。
man 3 posix_madvise
说:
相应的 madvise(2) 值 MADV_DONTNEED 具有破坏性语义。
所以不,这不是纯粹的建议,是的,如果你到处盲目这样做,它可能会导致段错误。