[Linux内存]永久内存映射kmap

一:kmap()和kunmap()函数
永久内核映射允许内核建立高端页框到内核地址空间的长期映射。他使用主内核页表中一个专门的页表,其页表地址存放在pkmap_page_table中,页表包含512项或1024项,
因此,内核一次最多访问2M或4M的高端内存(地址范围是 4G-8M 到 4G-4M 之间,这个地址空间起叫“内核永久映射空间”或者“永久内核映射空间”)。
kmap()和kunmap()函数不能用于中断处理程序,因为其可能会睡眠。

pkmap_count是一个容量为LAST_PKMAP的整数数组,其中每个元素都对应一个持久映射页。
宏定义与关键变量定义:
 pkmap_page_table:高端内存主内核页表中,一个用于永久内核映射的专用页表锁在的地址
 LAST_PKMAP: 上述页表所含有的表项(512或者1024)
 PKMAP_BASE:该页表所映射线性地址的start地址
 pkmap_count:对页表项提供计数器的数组
 page_address_htable:散列表,用于记录高端页框与永久内核映射的线性地址之间的关系
 page_address_map:一个数据结构,包含指向页描述符的指针和分配给页框的线性地址;用于为高端内存的每
      个页框提供当前映射,它被包含在page_address_htable这个hansh表中

内核主要通过以下数据结构来建立物理页page与其在虚拟内存区位置的关联

[cpp] view plaincopy

  1. struct page_address_map {        //页地址映射
  2. struct page *page;            //页的描述结构
  3. void *virtual;                //页的虚拟地址
  4. struct list_head list;           //通过list字段链接到页表池全局链表page_address_pool中或page_address_htable[hash_ptr(page,PA_HASH_ORDER)].lh
  5. };
  6. 1 void *kmap(struct page* page)
  7. 2 {
  8. 3     if(!PageHighMem(page))//判断是否是高端内存
  9. 4        return page_address(page);
  10. 5     return kmap_high(page);
  11. 6 }
  12. 7
  13. 8 void *kmap_high(struct page *page)
  14. 9 {
  15. 10     unsigned long vaddr;
  16. 11     spin_lock(&kmap_lock);//自旋锁
  17. 12    vaddr = (unsigned long) page_address(page);
  18. 13     if(!vaddr)   //如果该page在虚拟内存中部对应有效的地址,那么调用map_new_virtual()函数进行映射该页,
  19. 14         vaddr = map_new_virtual(page);
  20. 15     pkmap_count[(vaddr - PKMAP_BASE) >> PAGE_SHIFT]++;//pkamp_count数组包含LAST_PKAMP个计数器
  21. 16     spin_unlock(&kmap_lock);
  22. 17      return (void *) vaddr;
  23. 18 }

二:kmap_atomic()临时内存函数
kmap_atomic()函数主要用于建立临时内存映射,它不能用于可能建立睡眠的代码。

时间: 2024-08-24 08:24:30

[Linux内存]永久内存映射kmap的相关文章

Linux高端内存映射

概述 在32位的系统上,内核占有从第3GB~第4GB的线性地址空间,共1GB大小,内核将其中的前896MB与物理内存的0~896MB进行直接映射,即线性映射,将剩余的128M线性地址空间作为访问高于896M的内存的一个窗口. 引入高端内存映射这样一个概念的主要原因就是我们所安装的内存大于1G时,内核的1G线性地址空间无法建立一个完全的直接映射来触及整个物理内存空间,而对于80x86开启PAE的情况下,允许的最大物理内存可达到64G,因此内核将自己的最后128M的线性地址空间腾出来,用以完成对高端

Linux高端内存映射(上)【转】

转自:http://blog.csdn.net/vanbreaker/article/details/7579941 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 高端内存概述 永久内核映射 高端内存概述 在32位的系统上,内核占有从第3GB~第4GB的线性地址空间,共1GB大小,内核将其中的前896MB与物理内存的0~896MB进行直接映射,即线性映射,将剩余的128M线性地址空间作为访问高于896M的内存的一个窗口.引入高端内存映射这样一个概念的主要原因就是我们所安

Linux的mmap内存映射机制解析

在讲述文件映射的概念时,不可避免的要牵涉到虚存(SVR 4的VM).实际上,文件映射是虚存的中心概念, 文件映射一方面给用户提供了一组措施,好似用户将文件映射到自己地址空间的某个部分,使用简单的内存访问指令读写文件:另一方面,它也可以用于内核的基本组织模式,在这种模式种,内核将整个地址空间视为诸如文件之类的一组不同对象的映射.中的传统文件访问方式是,首先用open系统调用打开文件,然后使用read, write以及lseek等调用进行顺序或者随即的I/O.这种方式是非常低效的,每一次I/O操作都

(笔记)Linux内核中内存相关的操作函数

linux内核中内存相关的操作函数 1.kmalloc()/kfree() static __always_inline void *kmalloc(size_t size, gfp_t flags) 内核空间申请指定大小的内存区域,返回内核空间虚拟地址.在函数实现中,如果申请的内存空间较大的话,会从buddy系统申请若干内存页面,如果申请的内存空间大小较小的话,会从slab系统中申请内存空间.有关buddy和slab,请参见<linux内核之内存管理.doc> gfp_t flags 的选项

Linux高端内存的由来

抱着拿来主义,自己挑选了部分,以下内容摘自网络. Linux内核地址空间划分 通常32位Linux内核地址空间划分0~3G为用户空间,3~4G为内核空间.注意这里是32位内核地址空间划分,64位内核地址空间划分是不同的. Linux内核高端内存的由来 当内核模块代码或线程访问内存时,代码中的内存地址都为逻辑地址,而对应到真正的物理内存地址,需要地址一对一的映射,如逻辑地址0xc0000003对应的物理地址为0×3,0xc0000004对应的物理地址为0×4,- -,逻辑地址与物理地址对应的关系为

linux高端内存的理解

在linux中,地址空间映射是这样的,把0xc0000000-0xffffffff这1GB内核地址空间划分成2个部分低端的796MB + 高端的128MB,低端796MB就使用f映射,直接映射到物理内存的前796MB上,而高端128MB就用来随时变更g来映射到物理内存超过796MB的范围上,这里对应了3种映射算法:动态映射,永久内核映射,临时映射. 说下"映射"是什么,其实就是x86的内存分页机制,我们只要通过修改分页的页表项就可达到更改 "映射" 的目的. 查看系

Linux与jvm内存关系分析

原文出处: 美团技术团队 引言 在一些物理内存为8g的服务器上,主要运行一个Java服务,系统内存分配如下:Java服务的JVM堆大小设置为6g,一个监控进程占用大约600m,Linux自身使用大约800m.从表面上,物理内存应该是足够使用的:但实际运行的情况是,会发生大量使用SWAP(说明物理内存不够使用了),如下图所示.同时,由于SWAP和GC同时发生会致使JVM严重卡顿,所以我们要追问:内存究竟去哪儿了? 要分析这个问题,理解JVM和操作系统之间的内存关系非常重要.接下来主要就Linux与

Linux设备驱动--内存管理

MMU具有物理地址和虚拟地址转换,内存访问权限保护等功能.这使得Linux操作系统能单独为每个用户进程分配独立的内存空间并且保证用户空间不能访问内核空间的地址,为操作系统虚拟内存管理模块提供硬件基础. Linux内存管理 在Linux操作系统中,进程的4G空间被分成两个部分----用户空间和内核空间.用户空间一般为0~3GB(即PAGE_OFFSET,在X86系统中等于0xC0000000),而剩余的3GB~4GB为内核空间.用户进程在通常情况下只能访问用户空间的虚拟地址,不能访问内核空间的虚拟

Linux IPC 共享内存用法

Linux IPC 常见的方式 写 Linux Server 端程序,必然会涉及到进程间通信 IPC. 通信必然伴随着同步机制,下面是一些常见的通信与同步机制: 进程间通信:匿名管道,命名管道,消息队列,共享内存,Domain Socket, 本机 TCP Socket,文件 进程间同步:信号,信号量 线程间同步:条件变量,互斥量,读写锁,自旋锁,Barrier. 对于大部分的业务场景,本机 TCP Socket 足以,现在Linux 也对本机 TCP Socket做了很好的优化.而且如果以后需