在linux内核中,所有的物理内存都用struct page结构来描述,这些对象以数组形式存放,而这个数组的地址就是mem_map。...mem_map的作用 mem_map是一个数组,存放了所有的页描述符。一个页对应一个页描述符。...mem_map的定义 /* \linux\mm\memory.c */ #ifndef CONFIG_NEED_MULTIPLE_NODES /* use the per-pgdat data instead...也就是说,mem_map是node下一级的一个概念。...*/ alloc_node_mem_map源码分析 /* \linux\mm\page_alloc.c */ static void __ref alloc_node_mem_map(struct pglist_data
伙伴系统是常用的内存分配算法,linux内核的底层页分配算法就是伙伴系统,伙伴系统的优点就是分配和回收速度快,减少外部碎片。...然后又看了一下linux4.8的buddy system实现,linux的buddy system主要进行page分配也是linux最底层的分配,其他的分配算法都是以这个分配为基础,在x86架构下一个page...linux对内存进行了分区包括低端内存区,高端内存区,dma区,而且还对numa架构做了很多处理,对页面也进行了分类,这些不是讨论的重点,现在主要是提取linux的buddy算法,只提取核心部分,可以在控制台下运行...最大的是10,也就是1024个基本单位,所以linux在x86下一次最多可分配4MB内存。 ...PAGE_NUMS]; free_area_t free_area[MAX_ORDER]; #define PAGE_TO_PFN(page) ((unsigned int)(page - mem_map
/* * linux/mm/memory.c * * (C) 1991 Linus Torvalds */ /* * demand-loading started 01.12.91 -...invalidate()"s - I wasn't doing enough of them. */ #include #include #include #include #include volatile void do_exit(long code); static...[addr]--) return; mem_map[addr]=0; panic("trying to free free page"); } /* * This function...= 1) printk("mem_map disagrees with %p at %p\n",page,address); // 计算页目录项 page_table =
/* * linux/mm/memory.c * * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds */ /* * demand-loading...* Idea by Alex Bligh (alex@cconcepts.co.uk) */ #include #include #include #include #include #include ...#include #include #include #include ...*/ // 如果有多个进程在使用,则需要为执行写操作的进程,新增一个页表项,指向新页,如果只有一个进程在使用,则不需要 if (mem_map[MAP_NR(old_page)] !
物理地址空间布局 Linux系统在初始化时,会根据实际的物理内存的大小,为每个物理页面创建一个page对象,所有的page对象构成一个mem_map数组。...Linux内核空间虚拟地址分布 ? 在 Kernel Image 下面有 16M 的内核空间用于 DMA 操作。...由于 ZONE_NORMAL 和内核线性空间存在直接映射关系,所以内核会将频繁使用的数据如 Kernel 代码、GDT、IDT、PGD、mem_map 数组等放在 ZONE_NORMAL 里。...Linux物理地址和虚拟地址的关系 ? Linux 将 4G 的线性地址空间分为2部分,0~3G 为 user space,3G~4G 为 kernel space。...到这里我们应该知道了 Linux 是如何用虚拟地址来映射物理地址的,最后我们用一张图来总结一下: ?
1 Linux如何描述物理内存 Linux把物理内存划分为三个层次来管理 层次 描述 存储节点(Node) CPU被划分为多个节点(node), 内存则被分簇, 每个CPU对应一个本地物理内存, 即一个...mem_map是一个struct page的数组,管理着系统中所有的物理内存页面。...在系统启动的过程中,创建和分配mem_map的内存区域, mem_map定义在mm/page_alloc.c?...; EXPORT_SYMBOL(max_mapnr); EXPORT_SYMBOL(mem_map); #endif UMA体系结构中, free_area_init函数在系统唯一的struct node...对象contig_page_data中node_mem_map成员赋值给全局的mem_map变量
---------------------------------------------------------- // dram.c // // This module implements a Linux...(mem_map结构体数组用来表示所有物理页) pfn(page frame number),是物理页号 (还是物理地址?...-a; //a[10]就好比page,a就好比mem_map,只不过mem_map是一个结构体数组 #define pfn_to_page(pfn) ((mem_map + (pfn)) - PHYS_PFN_OFFSET...Stop. make: *** [default] Error 2 参考 对于结构体指针+、-常数的理解(page_to_pfn和pfn_to_page) Linux用户程序如何访问物理内存 Linux...中的虚拟地址、物理地址和内存管理方式 利用mmap /dev/mem 读写Linux内存 判断内存地址是否缺页 写自己的内核模块——获取一个进程的物理地址 copy_from_user分析
若共享操作不成功,那么只能从相应文件中读入所缺的数据页面到指定线性地址处 //在linux/mm/memory.c中 //错误码和对应产生错误的虚拟地址 void do_no_page(unsigned...; } ---- put_page put_page用来完成物理页面与一个线性地址页面的挂接,从而将一个线性地址空间内的页面落实到物理地址空间内, page为物理地址,address为线性地址 //在linux...=1是检查这个page地址对应的物理内存页面 // 是不是已经注册过的页面(用get_free_page函数申请,申请时会再mem_map中 // 注册这个页面,也就是把这个页面对应的mem_map项加...=1就要警告) if (mem_map[(page-LOW_MEM)>>12] !...---- 参考 Linux内存管理之copy_page_tables源码理解
一、前言 在linux内核中支持3中内存模型,分别是flat memory model,Discontiguous memory model和sparse memory model。...所谓memory model,其实就是从cpu的角度看,其物理内存的分布情况,在linux kernel中,使用什么的方式来管理这些物理内存。...在linux操作系统中,物理内存是按照page size来管理的,具体page size是多少是和硬件以及linux系统配置相关的,4k是最经典的设定。...三、Linux 内核中的三种memory model 1、什么是FLAT memory model?...而,每个节点管理的物理内存保存在struct pglist_data 数据结构的node_mem_map成员中(概念类似flat memory中的mem_map)。
因此linux内核需要用一种体系结构无关的方式来表示内存....并不是所有的node都有3个zone的,比如一个CPU簇就可能没有ZONE_DMA区域 node_mem_map node中的第一个page,它可以指向mem_map中的任何一个page,指向page实例数组的指针...,用于描述该节点所拥有的的物理内存页,它包含了该页面所有的内存页,被放置在全局mem_map数组中 bdata 这个仅用于引导程序boot 的内存分配,内存在启动时,也需要使用内存,在这里内存使用了自举内存分配器...*/ /* /*起始页面帧号,指出该节点在全局mem_map中的偏移 系统中所有的页帧是依次编号的,每个页帧的号码都是全局唯一的(不只是结点内唯一) */ unsigned...; #define NODE_DATA(nid) (&contig_page_data) #define NODE_MEM_MAP(nid) mem_map else /*
1) FLATMEM 在这种情况下,宏_pfn_to_page的定义是: #define __pfn_to_page(pfn) (mem_map + ((pfn) - ARCH_PFN_OFFSET)...) 而这个mem_map的定义是 struct page *mem_map; 所以在这种情况下,page struct就是一个大数组,所有的人都按照自己的物理地址有序得挨着。...commit c4e1be9ec1130fff4d691cdc0e0f9d666009f9ae Author: Dave Hansen Date...为了看得清,我们把这两个定义再拿过来对比一下: 先看看FLATMEM时的定义: #define __pfn_to_page(pfn) (mem_map + ((pfn) - ARCH_PFN_OFFSET
= pte_val(entry)) { free_page(pte_page(page)); return; } if (mem_map[MAP_NR(pte_page(page))] >...... // 记录物理地址 shp->shm_pages[idx] = pte_val(pte); } mem_map
old_page对应的物理页引用数为1,可以直接修改内容,置可写标记位(第二位) if (old_page >= LOW_MEM && mem_map[MAP_NR(old_page)]==1)...get_free_page())) oom(); // 页的引用数减一,因为有一个进程不使用这块内存了 if (old_page >= LOW_MEM) mem_map
伙伴系统分配算法 在上一节, 我们介绍了Linux内核怎么管理系统中的物理内存....在Linux内核中, 把两个物理地址相邻的内存页当作成伙伴, 因为Linux是以页面号来管理内存页的, 所以就是说两个相邻页面号的页面是伙伴关系....Linux内核使用 free_area[i] 管理 2i 个内存页面大小的内存块列表....在后面的Linux版本中改进了这个问题....zone = page->zone; mask = (~0UL) << order; // 获取一个后order个位为0的长整型数字 base = mem_map + zone
2 (N)UMA模型中linux内存的机构 Linux适用于各种不同的体系结构, 而不同体系结构在内存管理方面的差别很大. 因此linux内核需要用一种体系结构无关的方式来表示内存....; #define NODE_DATA(nid) (&contig_page_data) #define NODE_MEM_MAP(nid) mem_map else /*...尤其是, Linux内核必须处理80x86体系结构的两种硬件约束....页的数据结构对象都保存在mem_map全局数组中,该数组通常被存放在ZONE_NORMAL的首部,或者就在小内存系统中为装入内核映像而预留的区域之后。...2.6 高端内存 由于能够被Linux内核直接访问的ZONE_NORMAL区域的内存空间也是有限的,所以LINUX提出了高端内存(High memory)的概念,并且允许对高端内存的访问
内存节点结构体在linux内核include/linux/mmzone.h文件中, /* * On NUMA machines, each NUMA node would have a pg_data_t...内存节点被划分为内存区域,内存区域结构体在linux内核include/linux/mmzone.h文件中 struct zone { unsigned long watermark[NR_WMARK...内存区域结构体在linux内核include/linux/mm_types.h文件中 struct page { unsigned long flags; /* Atomic flags, some...而,每个节点管理的物理内存保存在struct pglist_data 数据结构的node_mem_map成员中(概念类似flat memory中的mem_map)。...其实 Linux 倾向于另外一种从虚拟地址到物理地址的转换方式,称为分页(Paging)。
而我们今天要讲的boot阶段就是系统初始化阶段使用的内存分配器. 1 前景回顾 1.1 Linux内存管理的层次结构 Linux把物理内存划分为三个层次来管理 层次 描述 存储节点(Node) CPU被划分为多个节点...尤其是, Linux内核必须处理80x86体系结构的两种硬件约束....出于节省内存的考虑,struct page中使用了大量的联合体union. mem_map是一个struct page的数组,管理着系统中所有的物理内存页面。...在系统启动的过程中,创建和分配mem_map的内存区域, mem_map定义在mm/page_alloc.c?...因此我们可以把linux内核的内存管理分三个阶段。
printk("Trying to put page %p at %p\n",page,address); // page对应的物理页面没有被分配则说明有问题 if (mem_map...= 1) printk("mem_map disagrees with %p at %p\n",page,address); // 计算页目录项的偏移地址,页目录首地址再物理地址.../ 使tlb失效 invalidate(); // 算出页数,物理页引用数加一 phys_addr -= LOW_MEM; phys_addr >>= 12; mem_map
看完了进入内核前的工作后,我网络编程课的抄写作业自然是可以圆满完成啦,不过看了一部分后觉得确实很有意思,所以也是决定继续看下去,并且计划看完linux源码后跟着MIT6.s081写一个小的操作系统内核,...我们仍然使用8M大小的内存空间举例 可以看出,mem_map数组的每个元素都表示一个4K的内存空间是否空闲,4K内存通常叫做1页内存,这种内存管理方式叫做分页管理。...诶这个时候我们是不是又会想起来在进入Linux内核前的准备一文中提到过的INT指令,例如INT 0x80这个指令就是相当于直接告诉CPU中断号0x80。...那至于这里提到的中断描述符表IDT,我们也在进入Linux内核前的准备一文中设置GDT这一段中提到过啦,IDT从idtr寄存器中可以找到,而idt这个表采用的是一个结构体数组的方式进行存储,对应的内容就是上面提到的段选择子和段内偏移地址啦...并且呢当时在内存管理中,我们用mem_init()初始化了主内存的管理结构mem_map,以此来对内存进行管理。
领取专属 10元无门槛券
手把手带您无忧上云