MMU
一.What is MMU
1.ARM有多个协处理器,MMU是其中一个协处理器,用作内存管理。若应用程序想访问某块物理内存地址,MMU会将虚拟内存映射到物理内存。
2.MMU包括了页表(PT)和块表(TLB),TLB相当于PT的快速缓存。
二.What is it used for?
1.应用程序直接访问物理内存很危险,所以让MMU进行管理。
2.让每个进程都拥有了完整且相互独立的地址空间(页表),页表存储了进程中虚拟地址到物理地址的映射关系。
三.How it works?
1.页表PT
1.当cpu想要访问某个物理地址(内存),CPU就会发一个虚拟地址给MMU,MMU收到CPU的虚拟地址之后开始查询页表,确定是否存在映射以及读写权限是否正常。
2.MMU要先进行页表查询确定物理地址,
3.若找到页表中找到这个物理,在确认权限等问题后,MMU再将这个物理地址发送到总线,内存收到之后开始读取对应地址的数据。
4.若没找到,产生缺页中断(缺页异常)。
注意:(1.页表级数越多查询的步骤越多,对于CPU来说等待时间越长,效率越低。2.页表存在于进程的内存之中)
2.块表(TLB)
1.TLB相当于是PT的缓存,当CPU给MMU传新虚拟地址之后,MMU先看TLB那边有没有,如果有就直接拿到物理地址发到总线给内存。
2.TLB比较小,若TLB不存在cpu需要的内存地址,MMU会在在页表中;找到之后,MMU除了把地址发到总线传给内存,还把这条映射关系给到TLB,让它记录一下刷新缓存。
四.what's the problem with MMU?
1.page fault缺页异常
缺页异常有三种:Hard Page Fault、Soft Page Fault、Invalid Page Fault。
2.Hard Page Fault
物理内存中没有这个数据
也被称为Major Page Fault,翻译为硬缺页错误/主要缺页错误,这时物理内存中没有对应的页帧,需要执行页面替换算法,打开磁盘设备读取到物理内存中,再让MMU建立VA和PA的映射。
3.Soft Page Fault
其它进程有这个数据
也被称为Minor Page Fault,翻译为软缺页错误/次要缺页错误,这时物理内存中是存在对应页帧的,只不过可能是其他进程调入的,发出缺页异常的进程不知道而已,此时MMU只需要建立映射即可,无需从磁盘读取写入内存,一般出现在多进程共享内存区域。
4.Invalid Page Fault
翻译为无效缺页错误,比如进程访问的内存地址越界访问,又比如对空指针解引用内核就会报segment fault错误中断进程直接挂掉。
段错误:应用程序访问一个VA(virtual_addr),经MMU检查后发现无权访问,MMU就会产生一个异常。cpu从user_mod切换到特权模式,执行异常服务程序,内核会把这个异常解释为段错误,然后把相应的程序终止掉。
五.Use Case
1.lvgl的屏幕设备的内存映射
fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
这段代码的目的是将一个帧缓冲设备映射到进程的地址空间中,以便可以直接通文件句柄fbp,对实际内存进行写操作来控制显示输出。
点击查看代码
void fbdev_init(void)
{
// Open the file for reading and writing
fbfd = open(FBDEV_PATH, O_RDWR);
if(fbfd == -1) {
perror("Error: cannot open framebuffer device");
return;
}
LV_LOG_INFO("The framebuffer device was opened successfully");
#if FBDEV_DISPLAY_POWER_ON
// Make sure that the display is on.
if (ioctl(fbfd, FBIOBLANK, FB_BLANK_UNBLANK) != 0) {
perror("ioctl(FBIOBLANK)");
return;
}
#endif /* FBDEV_DISPLAY_POWER_ON */
// Get fixed screen information
if(ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) {
perror("Error reading fixed information");
return;
}
// Get variable screen information
if(ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
perror("Error reading variable information");
return;
}
dbg_printf("[sh]%dx%d, %dbpp\r\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
// Figure out the size of the screen in bytes
screensize = finfo.smem_len; //finfo.line_length * vinfo.yres;
// Map the device to memory
fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
if((intptr_t)fbp == -1) {
perror("Error: failed to map framebuffer device to memory");
return;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通