- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
TL;DR:内核究竟是如何在 /proc/$PID/smaps
中进行脏页统计的? ?
考虑以下 C 程序语句:
static char page1[PAGE_SIZE] __attribute__ ((aligned (PAGE_SIZE)));
现在未初始化的变量在开始时为零。我的理解是,在程序启动时,内核将未初始化的变量映射到零页,并对页面进行写时复制延迟分配。很好,有道理,这样内核就可以在发生页面错误时解决未初始化部分的脏页。
现在考虑语句:
static char page1[PAGE_SIZE] __attribute__ ((aligned (PAGE_SIZE))) = {'c'};
在这里,加载程序将加载 page1
的值在程序初始化时,和将页面标记为 RW。所以程序所做的任何写入对内核来说都是不可见的因为没有页面错误被触发。
下面是我写的实验程序:
#define PAGE_SIZE (4*1024)
static char page1[PAGE_SIZE] __attribute__ ((aligned (PAGE_SIZE))) = {'c'};
int main()
{
char c; int i; int *d;
scanf("%c", &c); // --------- tag 1
for(i = 0; i < PAGE_SIZE; i++)
{
page1[i] = c; // --------- tag 2
}
d = malloc(sizeof(int));
while(1);
return 0;
}
现在在标记 1 之前和标记 2 之后(代码中的注释),/proc/$PID/smaps
的输出对于包含 page1
的部分粘贴在下面的表格中:
如你所见,上面的粗体参数发生了变化。
问题:
Anonymous
字段,为什么会发生变化?任何其他详细解释所有工作的页面/博客/手册都会有所帮助。
我的猜测是,也许内核将页面标记为 RO,即使它是 RW,以便触发页面错误并且它可以进行统计。或者也许还有其他一些过程不断遍历进程的页表,但这似乎太昂贵了。
最佳答案
Now consider the statement
static char page1[PAGE_SIZE] __attribute__ ((aligned (PAGE_SIZE))) = {'c'}
Here, the loader will load the values for page1 at init of the program, and mark the page as RW.
您似乎认为加载程序会为这条语句写入内存,但实际上并没有。
在这种情况下发生的不是 mmap
RW + 写入字节 'c'
。该字节已在编译时嵌入到您的可执行文件中,因此唯一发生的是 mmap
RW,仅此而已。像这样:
mmap(0, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd_of_your_elf, offset_of_data_section);
或者,最有可能的是,只是 mmap(...entire file...)
后跟一系列具有不同部分的正确权限的 mprotect()
Sprite 的。
实际上,在这种情况下,甚至不是加载程序执行此操作,而是内核本身将可执行文件映射到内存,假设您将程序作为 ./exe
启动。加载程序仅在以 /path/to/loader./exe
调用时自行映射程序。另见 this other answer of mine在这里我有更详细的解释。
How on earth did the kernel got to know I wrote the page?
您可能已经知道,当您的程序最初映射到内存中时(包括包含 page1
的页面),即使该页面的映射是 RW,也没有真正需要内核实际为页面分配内存,直到发生读取或写入。这种技术被称为 demand paging .最初(在映射之后)该页面甚至不存在于您进程的页表中:它仅作为众多 vm_area_struct
之一存在。任务内存映射中的条目。
当发生页面错误(由读或写引起)时,内核会根据映射的性质决定要做什么。在这种情况下,映射是文件支持的(整个 page1
数组的实际初始值在编译时写入您的 ELF 文件),因此两种可能的情况如下:
当发生内存读取时,会发生页面错误,页面内容会从文件中读取到内存中。新分配的页面现在被标记为只读,即使它被映射为 RW(内核仍然知道这个 VMA 是 RW)。
当发生内存写入时,有两种情况:要么 (A) 由于之前的读取,页面已经存在于内存中(并且是标记为 RO),或者 (B) 该页面根本不在内存中,因为这是对其的第一次内存访问。在这两种情况下,都会发生页面错误,内核会检查是否允许写入(是的),并且 copy-on-write发生。
由于该页面是文件备份的,但未共享(即未使用 MAP_SHARED
进行映射),因此不需要将数据写回到文件中,因此内核简单地分配一个新的匿名页面,然后从前一页复制内容(情况A)或从文件中读取页面到内存中(情况 B) 在应用写入之前。这就是您看到 Anonymous
从 0kB 变为 4kB 的原因。
此外,由于旧页面在写时复制之前只有一个用户,它可以被释放,这就是您看到 Rss
保持不变的原因。最后,在写入之前页面是干净的(不脏),写入之后它变脏了(不干净),所以这就是为什么您看到 Private_Clean
和 Private_Dirty
发生变化的原因值(value)观。
关于c - 通过/proc/$PID/smaps 在 Linux 内核中进行脏页统计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70822002/
我不知道这是不是问这个问题的正确论坛,但我是 stackoverflow 的粉丝,所以决定继续在这里发布它。 如果我输出/proc//smaps,我发现有几个段没有与之关联的任何名称,并且 inode
我得到了一个进程的堆栈内存信息: cat /proc/17647/smaps |grep stack 7ffff8840000-7ffff8853000 rwxp 7ffffffe9000 00:00
我正在寻找一个简短的 awk/sed 脚本来从具有以下记录格式的 proc/smaps 文件中提取 rss 信息: 77f73000-77f74000 rw-s 00000000 fd:00 2301
我必须制作一个 bash 脚本来启动 /proc/$pid/smaps 以下信息,而不是: total memory: 2mb Memory resident: 3kb private memory
我找不到关于/proc/pid/smaps 中 [vectors] 含义的任何信息。这是我的一些 smaps 文件的连续部分: 76eec000-76f11000 rw-p 0025b000 00:0
我正在尝试解析来自 /proc//smaps 的 PSS 值我的 C++ 二进制文件中的一个进程。 根据 this SO answer ,天真地读了/proc//smaps文件例如 ifstream:
我们需要通过 cron 每分钟监控我们高负载服务的内存使用情况。 为此,我们正在读取 /proc/PID/smaps 并以某种方式解析它。 但我们每时每刻都在遇到计时问题。关闭监控 cron 时,不存
它们总是 4kB 的倍数吗?将 smap 中的所有 Sizes 加起来有多大? 最佳答案 那里的粒度是内存页面大小。它可能是 4096 或 8192 字节(或者甚至是其他东西,不确定)。通常您可以使用
如何使用/proc/[PID]/maps 或/proc/[PID]/smaps 查找进程使用的 RAM 百分比,如下所示: 谢谢 最佳答案 你可以看看htop man:https://linux.di
我需要在Linux系统上解析“proc/pid/smaps”的输出。在此系统上运行 perl/python 脚本不是一个选项。我想看看是否有一个 bash 脚本可以做同样的事情。 或者,如果有一个脚本
我想知道 Linux 内核如何在执行 copy_from_user() 函数时禁用 x86 SMAP。我试图在源代码中找到一些东西,但我失败了。 Supervisor Mode Access Prev
我想知道如何从 linux 内核启用或禁用这 3 个功能: 卡斯尔 工作人员 map 我读过我必须在内核的命令行中添加一些东西才能启用此功能。我查看了/proc/cmdline。我没有看到任何关于 s
我找到了 this perl script that parses linux smaps , 但它似乎有点过时了: #!/usr/bin/perl # Copyright Ben Maurer #
TL;DR:内核究竟是如何在 /proc/$PID/smaps 中进行脏页统计的? ? 考虑以下 C 程序语句: static char page1[PAGE_SIZE] __attribute__
当使用 JSP 或其他转换为 Java 源代码(或 stub )的语言时,通常会生成一个 SMAP 文件,稍后可以将其嵌入到类文件中以供调试器显示更好的堆栈跟踪(或在对于 Jasper,它会自动嵌入)
我有一个 C++ gcc 泄漏程序,有 326 个部分,如下所示 33300000-33500000 rwxp 33300000 00:00 0 Size: 2048 kB
似乎(通过查看 Linux 内核 source)Swap: 中的指标 /proc/pid/smaps 是给定可访问的总交换pid. 在涉及共享内存的情况下,这似乎是对实际交换使用情况的过度估计。例如,
我的大型 Java 应用程序似乎存在巨大的内存泄漏。但泄漏似乎并不在 JVM 内存本身(即:堆、伊甸园、幸存者、代码、perm_gen 等)内,因为我没有用完这种类型的内存(即:它在使用过程中上升,但
我想计算单个进程的内存使用量。因此,经过一些研究后,我发现了 smaps 和 statm。 首先什么是smaps和statm?有什么区别? statm 有一个 RSS 字段,在 smaps 中我总结了
我一直在搜索依赖注入(inject)并阅读了一些文章。但我仍然无法找出 MEF 和其他 IoC 之间的区别。所以,我的问题是:在哪种情况下我应该更喜欢使用 MEF 或 IoC 容器? 为什么将 MEF
我是一名优秀的程序员,十分优秀!