作业地址

主要是实现一个 faulting 机制用于处理大平方根值表中根据平方根值计算得到的对应页面的 page fault

实现前编译运行结果

1
2
3
4
5
$ gcc mmap.c -lm -o mmap
$ ./mmap
page_size is 4096
Validating square root table contents...
oops got SIGSEGV at 0x7f6bf7fd7f18

根据作业的提示步骤实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
static void
handle_sigsegv(int sig, siginfo_t *si, void *ctx)
{
  uintptr_t fault_addr = (uintptr_t)si->si_addr;
  // Your code here.
  // replace these three lines with your implementation
  // Modify the code in handle_sigsegv() to
  // map in a page at the faulting address

  // unmap a previous page to stay within the physical memory limit
  static void *last_mapped_addr = NULL;
  if (last_mapped_addr) {
    if (munmap(last_mapped_addr, page_size) == -1) {
      fprintf(stderr, "Couldn't mmap() region for sqrt table; %s\n",
              strerror(errno));
      exit(EXIT_FAILURE);
    }
  }

  // initialize the new page with the correct square root values

  // 1. mmap a new page
  if ((last_mapped_addr = mmap((void *)fault_addr, page_size, PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) == MAP_FAILED) {
      fprintf(stderr, "Couldn't mmap() region for sqrt table; %s\n",
              strerror(errno));
      exit(EXIT_FAILURE);
  }

  // 2. Use the function calculate_sqrts() to compute the values
  calculate_sqrts((double *)last_mapped_addr, (double *)last_mapped_addr - sqrts, page_size / sizeof(double));

}

实现后运行结果

1
2
3
4
$ ./a.out
page_size is 4096
Validating square root table contents...
All tests passed!