c - 如何引发页面错误

标签 c linux memory-management linux-kernel virtual-memory

即使页表条目已经存在,我也想故意生成一个页面错误。

所以我清除了一个 _PAGE_PRESENT 位来生成页面错误。

这是我写的内核代码:

pte = get_locked_pte(mm, addr, &ptl);
entry = *pte;
entry = pte_clear_flags(entry, _PAGE_PRESENT);
set_pte_at(mm, addr, pte, entry);
pte_unmap_unlock(pte, ptl);
flush_tlb_range(vma, vma->vm_start, vma->vm_end);

但是,这段代码不起作用。我想要的页面错误没有发生。我想确切地知道如何触发页面错误。

谢谢。

最佳答案

@Jungsik Choi,当您为当前页面设置 NOT PRESENT 标志时,您破坏了页表条目,实际上将标志更改为 NOT PRESENT 没有任何作用,只会更改标志。所以你的页面实际上仍然存在。通过以这种方式设置 NOT PRESENT 标志,您将破坏 PTE,而不是引发页面错误。

如果你想观察页面错误,你需要强制从磁盘读取。以下代码映射命令行上给出的文件,告诉内核它不需要它;如果文件足够大(在/usr/bin 中选择一个大文件),您将始终遇到主要页面错误:

#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>

int main(int argc, char ** argv) {
  int fd = open(argv[1], O_RDONLY);
  struct stat stats;
  fstat(fd, &stats);
  posix_fadvise(fd, 0, stats.st_size, POSIX_FADV_DONTNEED);
  char * map = (char *) mmap(NULL, stats.st_size, PROT_READ, MAP_SHARED, fd, 0);
  if (map == MAP_FAILED) {
    perror("Failed to mmap");
    return 1;
  }
  int result = 0;
  int i;
  for (i = 0; i < stats.st_size; i++) {
    result += map[i];
  }
  munmap(map, stats.st_size);
  return result;
}

错误处理的方式并不多,这只是为了演示这个想法。在我的系统上,

gcc majorfault.c -o majorfault && /usr/bin/time -v ./majorfault /usr/bin/git-annex

总是产生 154 个主要页面错误。

关于c - 如何引发页面错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41068321/

相关文章:

c - 删除元素时如何填充数组间隙?

c - 将变量引用到现有数组

c - 如何解决我的小写函数遇到的这个问题

linux - 使用 ImageMagick 递归地转换所有图像颜色的正确命令

c - 为什么 '\b' 在下面的 C 代码中不起作用?

python - 在 IPython 中释放巨大的 numpy 数组的内存

macos - 在 MacOS 上计算每个进程的内存使用情况

c - Windows 上 C 的 IDE 建议

python - Jupyterhub 在没有 root 的情况下使用 sudo : can't run sudospawner without pw

c++ - 复制构造函数中的内存泄漏