警告:这很长,但我希望它将来对像我这样的人有用。
我想我知道程序计数器是什么,惰性内存分配是如何工作的,MMU 是做什么的,虚拟内存地址如何映射到物理地址以及 L1、L2 缓存的用途。我真正遇到的问题是,当我们运行 C 代码时,它们如何在高层次上结合在一起。
假设我有这个 C 代码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* ptr;
int n = 1000000, i = 0;
// Dynamically allocate memory using malloc()
ptr = (int*)malloc(n * sizeof(int));
ptr[0] = 99;
i += 100;
printf("%d\n", ptr[0]);
free(ptr);
return 0;
}
因此,这是我尝试将所有内容放在一起的尝试:
调用后
execve()
,可执行文件的一部分被加载到内存中,例如文本和数据段,但大部分代码不是——它们是按需加载的(按需分页)。第一条指令的地址在进程表的程序计数器 (PC) 字段中以及物理上的 PC 寄存器中,随时可以使用。
随着 CPU 执行指令,PC 被更新(通常 +1,但跳转可以转到不同的地址)。
进入主函数:
ptr
,n
, 和i
在堆栈中。接下来,当我们调用 时
malloc
,C 库将要求操作系统(我认为是通过sbrk()
sys 调用,或者是mmap()
吗?)在堆上分配一些内存。malloc
在这种情况下成功,返回一个虚拟内存地址 (VMA),但物理内存可能尚未分配。页表中不包含 VMA,因此当 CPU 尝试访问此类 VMA 时,会产生页面错误。在我们的例子中,当我们这样做时
ptr[0] = 99
,CPU 会引发页面错误。我不确定是分配了整个数组还是仅分配了第一页(4k 大小)。
但是现在我不知道如何将缓存访问放入图片中。如何i
放入L1缓存?它与 VMA 有什么关系?
对不起,如果这令人困惑。我只是希望有人可以帮助我完成整个过程......