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;
    }
}
posted @   Charles_hui  阅读(44)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示