【问题标题】:How to raise a page fault如何引发页面错误
【发布时间】:2016-12-09 20:25:25
【问题描述】:

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

所以我清除了_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);

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

谢谢。

【问题讨论】:

  • 你想写内核代码还是用户态代码?
  • 您是否正在编写内核代码来触发用户级代码中的页面错误?
  • 以上代码为内核代码。在上面的代码中,“addr”是用户空间的地址。
  • @JungsikChoi 你如何检查它没有发生?

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


【解决方案1】:

@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 个主要页面错误。

【讨论】:

    猜你喜欢
    • 2013-05-18
    • 2015-03-24
    • 2011-06-25
    • 2017-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-17
    相关资源
    最近更新 更多