Linux内核之内存管理(4)--缺页处理程序
本文主要解说缺页处理程序,凝视足够具体,不再解释。
//以下函数将一页内存页面映射到指定线性地址处,它返回页面的物理地址
//把一物理内存页面映射到线性地址空间指定处或者说把线性地址空间指定地址address处的页面映射到主内存区页面page上。主要工作是在相关也文件夹项和页表项中设置指定页面的信息。在处理缺页异常函数do_no_page中会调用这个函数。
參数:address--线性地址;page--是分配的主内存区中某一页面指针
static unsigned long put_page(unsigned long page,unsigned long address)
{
unsigned long tmp,*page_table;
//首先判定给定page的有效性。假设该页面位于LOW_MEM或者超出系统高端内存HIGH_MEMORY,则发出警告。再查看一下page是不是已经分配的页面。若没有发出警告,即判定其在内存页面映射字节图mem_map[]中相应字节是否已经置位。
if(page<LOW_MEM || page>=HIGH_MEMORY)
printk("Trying to put page at %p at %p",page,address);
if(mem_map[(page-LOW_MEM)>>12]!=1)
printk("mem_map disagrees with %p at %p\n",page,address);
//依据參数指定的线性地址address计算其在页文件夹表中相应的文件夹项指针,并从中取得二级页表地址。假设该文件夹项有效(p=1),即指定的页表在内存中,则从中取得指定页表地址放到page_table变量中,否则申请一空暇页面给页表使用,并在相应文件夹项中设置相应标志,然后将该页表地址放到page_table变量中
page_table=(unsigned long *)((address>>20) & 0xffc)
if((*page_table) & 1)
page_table=(unsigned long *) (0xfffff000 & *page_table);
else
{
if(!(tmp=get_free_page())
return 0;
*page_table=tmp|7;
page_table=(unsigned long *)tmp;
}
page_table[(address>>12) &0x3ff]=page|7;
return page;
}
//运行缺页处理,页异常中断处理过程中调用的函数。在page.s程序中被调用。函数參数error_code和address是进程在訪问页面时由CPU因缺页产生异常而自己主动生成。error_code指出出错类型,address是产生缺页的线性地址。
//该函数首先查看所缺页是否在交换设备中,若是则交换进来。否则尝试与已载入的同样文件进行页面共享,或者仅仅是由于进程动态申请内存页面仅仅需映射一页物理内存页就可以。若共享操作不成功,那么仅仅能从相应文件里读入所缺的数据页面到指定线性地址处
void do_no_page(unsigned long error_code,unsigned long address)
{
int nr[4];
unsigned long tmp;
unsigned long page;
int block,i;
struct m_inode *inode; if(address<TASK_SIZE)
printk("\n\rBAD! KERNEL PAGE MISSING\n\r");
if(address-current->start_code>TASK_SIZE)
{
printk("Bad things happen:nonexistent page error in no_page\n\r");
do_exit(SIGSEGV);
}
//然后依据指定的线性地址address求出其相应的二级页表项指针,并依据该页表项内容推断address处的页面是否在交换设备中。若是则调入页面并退出。方法是首先取指定线性地址address相应的文件夹项内容。假设相应二级页表存在,则取出该文件夹项中二级页表的地址,加上页表项偏移即得线性地址address相应的页面指针,从而获得页表项的内容。若页表项内容不为0而且页表项存在为P=0,则说明该页表项指定的物理页面应该在交换设备中。于是从交换设备中调入指定页面后退出
page=*(unsigned long *)((address>>20) & 0xffc);
if(page & 1)
{
page &=0xfffff000;
page+=(address>>10) & 0xffc
tmp=*(unsigned long *)page;
if(tmp && !(1 & tmp))
{
swap_in(unsigned long*)page);
return;
}
}
//否则取线性空间中指定地址address处页面地址,并计算出指定线性地址在进程空间中相对于进程基址的偏移长度值tmp,即相应的逻辑地址。从而能够算出缺页页面在运行文件映像或在库文件里的详细起始数据块号。由于设备上存放的可运行文件映像第1块数据是程序头结构,因此在读取该文件时须要跳过第一块数据。所以须要首先计算缺页所在的数据块号。由于每块数据长度为BLOCK_SIZE=1KB,因此一页内存可存放4个数据块。进程逻辑地址tmp除以数据块大小再加1就可以得处缺少页面在运行映像文件里起始块号block。
address &=0xfffff000;
tmp=address-current->start_code; if(tmp>=LIBRARY_OFFSET){
inode=current->library;
block=1+(tmp-LIBRARY_OFFSET);
}
else if(tmp<current->end_data){
inode=current->executable;
block=1+tmp/BLOCK_SIZE;
}else{
inode=NULL;
block=0
}
//是动态申请的数据内存页面
if(!node)
{
get_empty_page(address);
return;
}
//尝试共享tmp处的物理页面
if(share_page(inode,tmp))
return;
if(!(page=get_free_page()))
oom(); for(i=0;i<4;block++,i++)
nr[i]=bmap(inode,block);
bread_page(page,inode->i_dev,nr);
...
if(put_page(page,address))
return;
free_page(page);
oom();
}</span>
Linux内核之内存管理(4)--缺页处理程序的更多相关文章
- Linux内核笔记--内存管理之用户态进程内存分配
内核版本:linux-2.6.11 Linux在加载一个可执行程序的时候做了种种复杂的工作,内存分配是其中非常重要的一环,作为一个linux程序员必然会想要知道这个过程到底是怎么样的,内核源码会告诉你 ...
- Linux内核之内存管理
Linux内核之内存管理 Linux利用的是分段+分页单元把逻辑地址转换为物理地址; RAM的某些部分永久地分配给内核, 并用来存放内核代码以及静态内核数据结构; RAM的其余部分称动态内存(dyna ...
- 24小时学通Linux内核之内存管理方式
昨天分析的进程的代码让自己还在头昏目眩,脑子中这几天都是关于Linux内核的,对于自己出现的一些问题我会继续改正,希望和大家好好分享,共同进步.今天将会讲诉Linux如何追踪和管理用户空间进程的可用内 ...
- 深入理解Linux内核-内存管理
内核如果给自己分配动态内存 动态内存:RAM的某些部分被永久打分配给内核,用来存放内核代码以及静态内核数据结构:剩余的部分被称为动态内存 连续物理内存区管理: 页框管理:1.页大小的选择,通常情况下主 ...
- Linux内核笔记——内存管理之slab分配器
内核版本:linux-2.6.11 内存区和内存对象 伙伴系统是linux用于满足对不同大小块内存分配和释放请求的解决方案,它为slab分配器提供页框分配请求的实现. 如果我们需要请求具有连续物理地址 ...
- Linux内核之内存管理完全剖析
linux虚拟内存管理功能 ? 大地址空间:? 进程保护:? 内存映射:? 公平的物理内存分配:? 共享虚拟内存.实现结构剖析 (1)内存映射模块(mmap):负责把磁盘文件的逻辑地址映射到虚拟地 ...
- Linux 内核开发 - 内存管理
1.1什么是内存管理 内存管理是对计算机内存进行分配和使用的技术.内存管理主要存在于多任务的操作系统中,因为内存资源极其有限.须要在不同的任务之间共享内存,内存管理的存在就是要高效.高速的非配内存,并 ...
- Linux内核之 内存管理
前面几篇介绍了进程的一些知识,从这篇开始介绍内存.文件.IO等知识,发现更不好写哈哈.但还是有必要记录下自己的所学所思.供后续翻阅,同时写作也是一个巩固的过程. 这些知识以前有文档涉及过,但是角度不同 ...
- Linux内核笔记——内存管理之块内存分配
内核版本:linux-2.6.11 伙伴系统 伙伴系统是linux用于满足对不同大小块物理内存分配和释放请求的解决方案. 内存管理区 linux将物理内存分成三个内存管理区,分别为ZONE_DMA Z ...
随机推荐
- Android开发之动画(转)
activity跳转的过渡效果,很漂亮,很全 注意,切换方法overridePendingTransition只能在startActivity和finish方法之后调用. 第一个参数为第一个Activ ...
- 使用net start mysql的时候出现服务名无效的原因及解决办法
原因:mysql服务没有安装 解决办法:使用管理员权限,执行mysqld -install命令 然后以管理员身份net start mysql开启mysql服务 卸载mysql服务的方法 1.管理员权 ...
- git log
http://git-scm.com/book/zh/v2 https://backlogtool.com/git-guide/tw/contents/ http://gitbook.liuh ...
- poj3468(线段树 边覆盖)
#include<cstdio> int lb,rb,data; long long sum[5000000],extra[5000000]; void add(int l,int r,i ...
- codevs3732 解方程
%%%.设f(x)=a0+a1x+a2x^2+ - + anx^n.求f(x)=0的x. 数据范围很大,高精度只能骗分. 运用类似hash的思想. 如果这个等式mod p 还成立(p为质数)那它很可能 ...
- 【 D3.js 高级系列 — 1.0 】 文本的换行
在 SVG 中添加文本是使用 text 元素.但是,这个元素不能够自动换行,超出的部分就显示不出来了,怎么办呢? 高级系列开篇前言 从今天开始写高级系列教程.还是那句话,由于本人实力有限,不一定保证入 ...
- 学习面试题Day06
1.字节流的处理方式 字节流处理的是计算机最基本的单位byte,它可以处理任何数据格式的数据.主要的操作对象就是byte数组,通过read()和write()方法把byte数组中的数据写入或读出. 2 ...
- 声明顺序 (Bootstrap 编码规范)
相关的属性声明应当归为一组,并按照下面的顺序排列: Positioning Box model Typographic Visual 由于定位(positioning)可以从正常的文档流中移除元素,并 ...
- Ext入门学习系列(五)表格控件(3)
上节学习了Ext中如何绑定服务器端传递的数据.分别用asp.net和asp.net MVC.PHP.XML为例.本节主要介绍绑定之后的分页功能. 一.Ext的表格控件如何绑定? 分页是Ext自带的一个 ...
- (转)INSTALLSHIELD 2010 预安装组件和软件
使用Installshield2010提供的组件 大家再开发软件产品的时候经常是基于某些软件和类库的,像我们的项目就用到了.Net Framework3.5,mapinfo,sqlserver 200 ...