[Linux驱动入门]内存管理
来源:互联网 发布:淘宝比较出名的零食店 编辑:程序博客网 时间:2024/06/05 02:43
第六章 内存管理
6.1 内存管理中的基本概念
1. 页
内核把物理页作为内存管理的基本单位。大多数32位体系结构的处理器支持4KB的页,内核用struct page结构表示系统的物理页,这个page与物理页无关,而并非与虚拟页相关。页的拥有者可能是用户空间进程、动态分配的内核数据、静态内核代码或页高速缓存等。
2. 区
由于有些页位于内存特定的物理地址上,所以不能将其用于一些特定的任务,故内核把页分成不同的区,分别是ZONE_DMA,ZONE_DMA32,ZONE_NORMAL,ZONE_HIGHMEM.
6.2 申请内存的几种方法
alloc_page + page_address = _get_free_pages:需要以页为单位的一族连续物理页时,尤其只需要一两页。
kmalloc:连续的物理页。传递给这个函数的常用标志GFP_KERNEL和GPF_ATOMIC.
vmalloc:不需要连续的物理地址,只要连续的虚拟地址。
alloc_pages:需要从高端内存进行分配(高端内存物理地址高于896MB中的页被映射到3~4GB上)
如果需要创建和撤销很多大的数据结构,就需要考虑建立slab缓存,能极大地提高对象分配和回收的性能。
slab分配器的使用:
struct kmem_cache * task_struct_cachep;
task_struct_cachep = kmem_cache_create(“task_struct”,sizeof(task_struct),ARCH_MIN_TASKALIGN,SLAB_PANIC|SLAB_NOTRACK,NULL); //创建高速缓存
struct task_struct * tsk;
tsk = kmem_cache_alloc(task_struct_cachep,GPF_KERNEL); //从缓存中分配
……
kmem_cache_free(task_struct_cachep,tsk); //从缓存中释放
kmem_cache_destory(task_struct_cachep); //撤销高速缓存
6.3 内核栈
每个进程都有两个页的内核栈,32位和64位体系结构处理器的页面大小分别是4KB和8KB,所以内核栈的大小分别为8KB和16KB。由于连续两页有时难以寻找到,所以引入单页内核栈。当使用一个页面的内核栈时,中断处理程序就不放在栈里,为每一个进程提供一个用于中断处理程序的栈,即中断栈,这样中断处理程序不用再和被中断进程共享一个内核栈。
中断处理程序和被中断的进程共享一个栈,不过当1页栈被激活,中断处理程序就获得自己的栈。
6.4 进程地址空间的基本概念
进程地址空间:用户空间中的进程的内存
内核使用内存描述符结构体表示进程的地址空间,内存描述符由struct mm_struct结构体表示。分配内存描述符有两种方法:其一:fork函数利用copy_mm函数复制父进程的内存描述符,也就是current->mm域给子进程,而子进程中的mm_struct结构体实际上是通过allocate_mm宏从mm_cachep_slab缓存中分配得到的;其二,当CLONE_VM被指定后,内核就不需要调用allocate_mm函数,而仅仅需要在调用copy_mm函数中将mm域指向其父进程的内存描述符。
1.内核线程与内存描述符
内核线程没有进程地址空间,也就没有自己的内存描述符,内核线程是没有用户上下文的。为了避免内核线程为内核描述符分配页表浪费内存,内核线程直接使用前一个进程的内存描述符,而且仅仅使用前一个进程的描述符中和内核内存相关的信息,这些信息的含义和普通进程完全相同。
2.内存区域的树形结构和内存区域的链表结构
红黑树特点:
(1)左边节点值小于右边节点值;
(2)红节点的子节点为黑色;
(3)树中的任何一条从节点到叶子的路径必须包括相同数量的黑色节点;
(4)根节点为红色;
(5)红黑色搜索、插入、删除等操作的复杂度都是Olog(n);
链表用于需要遍历全部节点的时候,而红黑树适合在地址空间中定位特定内存区域的时候,内核为了内存区域上的不同的操作获得更高的性能,所以同时使用红黑树和链表这两种数据结构。
6.5 创建和撤销内存区域
如果创建内核区域,系统会调用do_mmap函数,在用户空间可以通过mmap函数获取内核函数do_mmap函数的功能。如果需要撤销内核区域,系统会调用do_mmap函数,在用户空间可以调用munmap函数获取内核do_munmap函数的功能。
原则上用户空间不能访问设备空间,mmap函数能把用户空间和设备空间进行映射,使得对用户空间的访问等同于对设备空间的访问。mmap具体功能有两个:其一,将普通文件映射到内存中,通常在需要对文件进行频繁读写时使用,这样用内存读写取代I/O读写,以获得较高的性能。其二,为无关联的进程提供共享内存空间,一般也是将一个普通文件映射到内存中。
用户调用mmap函数,内核会进行如下处理:
(1)在进程的虚拟空间查找一块VMA;
(2)将这块VMA进行映射;
(3)如果设备驱动程序或者文件系统的file_operations定义了mmap操作,
则调用它。
(4)将这个VMA插入进程的VMA链表中。
6.6 页表
当应用程序访问一个虚拟地址时,首先必须将虚拟地址转换为物理地址,然后处理器才能解析地址访问请求。地址转换需要将虚拟地址分段,使每段虚拟地址都作为一个索引指向页表。
搜索内存中物理地址速度有限,为了加快搜索,多数体系结构都实现了一个TLB(转换旁路缓存),TLB作为一个将虚拟地址映射到物理地址的硬件缓存。
6.7 页高速缓存与页回写
页高速缓存(cache)是Linux内核实现磁盘缓存,通过把磁盘中的数据缓存到物理内存中,把对磁盘的访问变为对物理内存的访问。页回写是将页高速缓存中的变更数据刷新回磁盘的操作。引入磁盘高速缓存的目的主要有两个:
(1)访问内存速度比访问磁盘快得多;
(2)临时局部原理;
读后备存储:首先检查需要的数据是否在页高速缓存中,如果在,则放弃访问磁盘,而直接从内存中读取,这个行为叫缓存命中。如果缓存未命中,那么内核必须调度块I/O操作,从磁盘读取数据,然后内核将读来的数据放入页缓存中,这样方便后期的缓存命中。
写缓存的方法如下:
(1)不缓存,即直接将数据写到磁盘,不通过页高速缓存;
(2)写透缓存,即写操作自动更新内存缓存,同时也更新磁盘文件;
(3)回写,即后备存储不立即直接更新,由一个回写进程周期性将脏页链表中的页写回磁盘,这样通过延迟写磁盘,可以方便在以后的时间内合并更多的数据和再一次刷新。
缓存回收:即缓存中的什么内容将被清除的策略。
基树:页高速缓存通过两个参数address_space对象上加一个偏移量进行搜索,每个address_space对象都有唯一的基树,它保存在address_space中的page_tree结构体中。
缓存区高速缓存:独立磁盘块通过I/O缓冲也要被存入页高速缓存,这个缓存叫做缓存区高速缓冲。
脏页被回写放生在如下三个条件:
(1)当空闲内存低于一个特定阈值时;
(2)当脏页在内存中驻留时间超过一个特定的阈值时;
(3)当用户进程调用syns()和fsync()系统调用时,内核会按要求执行回写操作。
- [Linux驱动入门]内存管理
- 【Linux驱动】内存管理
- [Linux驱动入门]进程管理
- Android/Linux Kernel 内存管理-入门笔记
- Android/Linux Kernel 内存管理-入门笔记
- Android/Linux Kernel 内存管理-入门笔记
- 《Linux驱动基础篇》- Linux内存管理篇
- 《Linux驱动基础篇》- Linux内存管理深入篇
- 驱动 内存管理 学习
- windows驱动内存管理
- Linux驱动学习12(初步认识内存管理)
- Linux内核驱动学习(四)----内存管理子系统
- Linux内核驱动学习(四)----内存管理子系统
- Linux设备驱动第九天(非阻塞、内存管理)
- WDF驱动中的内存管理
- linux驱动-内存分配
- linux驱动入门
- Linux驱动入门
- 思维导图构建Linuxt体系(持续更新)
- 第三周项目1-顺序表的基本运算
- Linux 常见命令 记住这些就够了
- HDU-5884 Sort
- 关系数据库规范化
- [Linux驱动入门]内存管理
- Oracle 11g R2 DBA 操作指南(17) 管理和维护表
- 静态库和动态库
- hibernate使用left join一点感悟
- java单例理解
- vs 2013 常用快捷键及常见问题的解决
- SPI总线
- SpringAOP与Redis搭建缓存
- Android--listview中每个item有多个控件的点击方法