我的过程中有多少个小错误*真的*正在服用?

时间:2017-01-02 18:02:21

标签: c linux memory-management mmap page-fault

我有以下简单程序,基本上只有mmap个文件并对其中的每个字节求和:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

volatile uint64_t sink;

int main(int argc, char** argv) {

  if (argc < 3) {
    puts("Usage: mmap_test FILE populate|nopopulate");
    return EXIT_FAILURE;
  }

  const char *filename = argv[1];
  int populate = !strcmp(argv[2], "populate");
  uint8_t *memblock;
  int fd;
  struct stat sb;

  fd = open(filename, O_RDONLY);
  fstat(fd, &sb);
  uint64_t size = sb.st_size;

  memblock = mmap(NULL, size, PROT_READ, MAP_SHARED | (populate ? MAP_POPULATE : 0), fd, 0);

  if (memblock == MAP_FAILED) {
    perror("mmap failed");
    return EXIT_FAILURE;
  }

  //printf("Opened %s of size %lu bytes\n", filename, size);  

  uint64_t i;
  uint8_t result = 0;
  for (i = 0; i < size; i++) {
    result += memblock[i];
  }

  sink = result;

  puts("Press enter to exit...");
  getchar();

  return EXIT_SUCCESS;
}

我这样做:

gcc -O2 -std=gnu99     mmap_test.c   -o mmap_test

您传递了一个文件名populatenopopulate 1 ,它控制MAP_POPULATE是否传递给mmap。在退出之前等待您输入回车(让您有时间查看/proc/<pid>中的内容或其他内容。)

我使用1GB的随机数据测试文件,但你真的可以使用任何东西:

dd bs=1MB count=1000 if=/dev/urandom of=/dev/shm/rand1g

当使用MAP_POPULATE时,我期望零主要错误以及页面缓存中文件的少量页面错误。使用perf stat,我得到了预期的结果:

perf stat -e major-faults,minor-faults ./mmap_test /dev/shm/rand1g populate
Press enter to exit...

 Performance counter stats for './mmap_test /dev/shm/rand1g populate':

                 0      major-faults                                                
                45      minor-faults                                                

       1.323418217 seconds time elapsed

45个故障只来自运行时和进程开销(并且不依赖于映射文件的大小)。

但是,/usr/bin/time报告了大约15,300个小故障:

 /usr/bin/time ./mmap_test /dev/shm/rand1g populate
Press enter to exit...

0.05user 0.05system 0:00.54elapsed 20%CPU (0avgtext+0avgdata 977744maxresident)k
0inputs+0outputs (0major+15318minor)pagefaults 0swaps

top和检查/proc/<pid>/stat报告了相同的~15,300个小故障。

现在,如果您不使用MAP_POPULATE,则所有方法(包括perf stat)都同意有大约15,300页错误。值得一提的是,这个数字来自1,000,000,000 / 4096 / 16 = ~15,250 - 也就是说,1GB除以4K页面,内核功能额外减少了16倍(&#34;故障&#34;)当发生故障时,页面缓存中已存在的最多15个附近页面出现故障。

谁在这?根据{{​​1}}记录的行为,MAP_POPULATE返回的数字是正确的 - 单perf stat调用已填充整个映射的页表,因此应该没有触摸它时会出现更多的小故障。

1 实际上,除 mmap以外的任何字符串都可以作为populate

0 个答案:

没有答案