c++ - 为什么这段代码会导致页面错误?

标签 c++ linux memory

我分配了 512mb 的内存,然后我修改了每 4096 个字节(这应该会导致每次修改都出现轻微的页面错误,这就是我实际得到的结果)。但随后我重复了相同的循环,它再次导致每个请求出现轻微的页面错误。我的问题是,为什么?

输出看起来像这样:

enter image description here

但是,如果我从我的程序中删除调用 ps,则执行第二个循环所需的时间会少得多,例如 0.04 秒。为什么?

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <sstream>
#include <unistd.h>
using namespace std;

const int sz = 512 * 1024 * 1024;

int main()
{
    char * data = (char *)malloc(sz);
    if (data == 0) cout << "alloc fail";
    stringstream cmd;
    cmd << "ps -o min_flt,maj_flt " << getpid();
    system(cmd.str().c_str());
    cout << "start\n";
    clock_t start = clock();
    for (int i=0; i<sz; i += 4096)
        data[i] = 1;
    clock_t end = clock();
    double time1 = double(end-start) / CLOCKS_PER_SEC;

    system(cmd.str().c_str());

    start = clock();
    for (int i = 0; i < sz; i += 4096)
        data[i] = 1;
    end = clock();
    double time2 = double(end-start) / CLOCKS_PER_SEC;

    system(cmd.str().c_str());

    cout << time1 << " " << time2 << endl;
}

最佳答案

库函数 system 大致做了以下事情:

  1. Fork,使用内存镜像的拷贝创建一个新进程。
  2. 在 child 中,exec /bin/sh 将命令行选项 -c 和指示的命令传递给它,替换内存带有新加载的/bin/sh 的新进程的图像。
  3. 在父进程(原进程)中,等待子进程完成,并返回其状态码。

当进程执行fork时,系统希望避免复制整个内存镜像以复制它。所以它只是复制页表,并将所有页面标记为“写时复制”,这需要将它们设置为只读以便可以检测到写入。

随后的 exec 会将页面标记为未共享,但它可能不会取消页面的只读设置,因此后续对页面的写入仍会触发轻微的页面错误,尽管处理程序不会执行任何操作,因为页面不再共享。

实际上不能保证 exec 会在第二个写循环开始之前发生。您的机器很可能有一个以上的内核,因此两个进程很可能同时处于事件状态。由于 exec 可能需要一段时间才能设置,因此很可能某些写循环甚至会在 exec 之前发生,也就是说在任何写时复制是不必要的线索。

关于c++ - 为什么这段代码会导致页面错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28079119/

相关文章:

linux - Windows 与 Linux 的内存使用情况

c++ - 如何在 llvm-ir 中模拟 thread_local?

c++ - mingw-w64 : slow sprintf in <cstdio>

python - 无法让 pyperclip 在 python3 上使用复制和粘贴模块

Python Tkinter : Attach scrollbar to listbox as opposed to window

批量for循环内存泄漏?

c++ - 多级指针作为参数 C++

c++ - 当用户键入定界符时,停止getline()输入

android 包管理器不能与 ICS 一起工作

Java线程内存计算