Linux内核内存管理( 二 )


在进程的虚拟地址空间中,代码段和数据段是私有的文件映射,未初始化数据段、堆和栈是私有的匿名映射 。
《内存映射的原理详解》
应用编程接口–>内存管理子系统提供如下常用的系统调用:
a.mmap()来创建内存映射 。void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);b.mremap()来扩大或缩小已经存在的内存映射,可能同时移动 。void * mremap(void *old_address, size_t old_size , size_t new_size, int flags);c.munmap()用来删除内存映射 。int munmap(void *addr, size_t length);d.brk()用来设备堆的上界 。int brk(void *addr);e.remap_file_pages()用来创建非线性的文件映射,即文件区间和虚拟地址空间之间的映射不是线性关系,现在已被废除 。int remap_file_pages(void *addr, size_t size, int prot,size_t pgoff, int flags);f.mprotect()用来设置虚拟内存区域的访问权限 。int mprotect(void *addr, size_t len, int prot);g.madvise()用来向内核提供提出内存使用的建议,应用程序告诉内核期望怎样使用指定的虚拟内存区域,以便内核可以选择适合的预读和缓存技术 。int madvise(void *addr, size_t length, int advice);
4、内存映射数据结构
1)虚拟内存区域:是分配给进程的一个虚拟地址范围,内核使用结构体描述虚拟内存区域:
5、创建内存映射
C标准库封装了函数mmap用来创建内存映射,内核提供POSIX标准定义的系统调用mmap如下:
6、虚拟内存提交策略
7、删除内存映射
二、内存模型/引导内存分配器
1、体系结构(NUMA、SMP)
2、内存模型(平坦内存、不连续内存、稀疏内存)
3、三级结构(node->zone->page)
4、分配器
5、分配器
6、物理内存数据信息
三、伙伴分配器/块分配器
1、伙伴分配器基本知识
2、分区的伙伴分配器(数据结构,首选/备用区域类型、区域水线)
3、每处理器页集合
4、分配页/释放页
5、块分配器编程接口实战
6、slab分配器、slub分配器、slob分配器
一、/系统调用
1、kmalloc()用于申请较小的/连续的物理内存,以字节为单位进行分配(在头文件)麒麟操作系统(UbuntuKylin)20.00以上函数原型如下:void *kmalloc(size_t size, int flags)// 分配的内存物理地址上连续,虚拟地址上自然连续![在这里插入图片描述](https://img-blog.csdnimg.cn/86275fd52d194e0caac39f3b61792d7e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA546755KD5pm05pyX5qmY5a2Q6L6J54WM,size_18,color_FFFFFF,t_70,g_se,x_16)2、void kfree(const void *ptr)释放由kmalloc()分配出来的内存块 。
3、()用于申请较大的内存空间,虚拟内存是连续的,以字节为单位进行分配(在头文件)
函数原型如下:
void *( long size) // 分配的内存虚拟地址上连续,物理地址不连续
一般情况下,只有硬件设备才需要物理地址连续的内存,因为硬件设备往往存在于MMU之外,根本不了解虚拟地址;但为了性能上的考虑,内核中一般使用 (),而只有在需要获得大块内存时才使用(),例如当模块被动态加载到内核当中时,就把模块装载到由()分配 的内存上 。
4、void vfree(void *addr)// 这个函数可以睡眠,因此不能从中断上下文调用 。
5、malloc(), vmalloc()和kmalloc()区别
和是分配的是内核的内存,分配的是用户的内存;
保证分配的内存在物理上是连续的,保证的是在虚拟地址空间上的连续,不保证任何东西;