本文主要解说缺页处理程序,凝视足够具体,不再解释。

//以下函数将一页内存页面映射到指定线性地址处,它返回页面的物理地址
//把一物理内存页面映射到线性地址空间指定处或者说把线性地址空间指定地址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)--缺页处理程序的更多相关文章

  1. Linux内核笔记--内存管理之用户态进程内存分配

    内核版本:linux-2.6.11 Linux在加载一个可执行程序的时候做了种种复杂的工作,内存分配是其中非常重要的一环,作为一个linux程序员必然会想要知道这个过程到底是怎么样的,内核源码会告诉你 ...

  2. Linux内核之内存管理

    Linux内核之内存管理 Linux利用的是分段+分页单元把逻辑地址转换为物理地址; RAM的某些部分永久地分配给内核, 并用来存放内核代码以及静态内核数据结构; RAM的其余部分称动态内存(dyna ...

  3. 24小时学通Linux内核之内存管理方式

    昨天分析的进程的代码让自己还在头昏目眩,脑子中这几天都是关于Linux内核的,对于自己出现的一些问题我会继续改正,希望和大家好好分享,共同进步.今天将会讲诉Linux如何追踪和管理用户空间进程的可用内 ...

  4. 深入理解Linux内核-内存管理

    内核如果给自己分配动态内存 动态内存:RAM的某些部分被永久打分配给内核,用来存放内核代码以及静态内核数据结构:剩余的部分被称为动态内存 连续物理内存区管理: 页框管理:1.页大小的选择,通常情况下主 ...

  5. Linux内核笔记——内存管理之slab分配器

    内核版本:linux-2.6.11 内存区和内存对象 伙伴系统是linux用于满足对不同大小块内存分配和释放请求的解决方案,它为slab分配器提供页框分配请求的实现. 如果我们需要请求具有连续物理地址 ...

  6. Linux内核之内存管理完全剖析

    linux虚拟内存管理功能 ? 大地址空间:? 进程保护:? 内存映射:? 公平的物理内存分配:? 共享虚拟内存.实现结构剖析   (1)内存映射模块(mmap):负责把磁盘文件的逻辑地址映射到虚拟地 ...

  7. Linux 内核开发 - 内存管理

    1.1什么是内存管理 内存管理是对计算机内存进行分配和使用的技术.内存管理主要存在于多任务的操作系统中,因为内存资源极其有限.须要在不同的任务之间共享内存,内存管理的存在就是要高效.高速的非配内存,并 ...

  8. Linux内核之 内存管理

    前面几篇介绍了进程的一些知识,从这篇开始介绍内存.文件.IO等知识,发现更不好写哈哈.但还是有必要记录下自己的所学所思.供后续翻阅,同时写作也是一个巩固的过程. 这些知识以前有文档涉及过,但是角度不同 ...

  9. Linux内核笔记——内存管理之块内存分配

    内核版本:linux-2.6.11 伙伴系统 伙伴系统是linux用于满足对不同大小块物理内存分配和释放请求的解决方案. 内存管理区 linux将物理内存分成三个内存管理区,分别为ZONE_DMA Z ...

随机推荐

  1. FastScroll(2)不分组的listview 打开fastscroll的分组提示功能

    本文只让fastscroll具有提示分组功能,但listview并不显示分组,如果想让分组的listview显示fastscroll,看下篇. 1,在listview中打开fastscroll 2,自 ...

  2. Pomelo服务器琐碎方法

    1.获取客户端ip地址:session__session__.__socket__remoteAddress.ip 2.日志文件无法打印到文件,删除node_modules/pomelo/node_m ...

  3. 宏page_t

    /** Type of the index page */ typedef byte page_t;

  4. 记一次SSH登陆失败问题的定位

    创建用户之后,使用ssh协议登陆提示失败. useradd -d /home/hdp -m hdp -g dba -s /bin/bash 通过命令 ssh -v hdp@127.0.0.1 登陆,查 ...

  5. Repeater实例应用

    在实际开发过程中,涉及到数据绑定,分页,以及一对多展示数据时,遇到这样的需求我们怎么解决呢?下面以帖子展示来逐一说明. 帖子主要由两部分组成,第一部分是发帖人的原创内容部分,第二部分是用户评论部分,这 ...

  6. Tomcat 配置问题总结

    本人是一个前端屌丝儿,最近没事研究了一下tomcat的部署问题,一下列几个实用的小技能(直接上干货了,不赘述): 1,路径引用部署 在tomcat目录下的conf/Catalina/localhost ...

  7. UVA 1349 Optimal Bus Route Design 最优公交路线(最小费用流,拆点)

    题意: 给若干景点,每个景点有若干单向边到达其他景点,要求规划一下公交路线,使得每个景点有车可达,并且每个景点只能有1车经过1次,公车必须走环形回到出发点(出发点走2次).问是否存在这样的线路?若存在 ...

  8. Java [leetcode 18]4Sum

    问题描述: Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d ...

  9. 解决android手机sd卡安装pak后直接打开,按home键异常问题

    if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) { finish(); return; }

  10. WCF学习笔记(二):简单调用

    转:http://www.cnblogs.com/wengyuli/archive/2009/11/08/1598428.html 一个通信会话过程有两个部分组成,客户端和服务端,他们要进行会话就必然 ...