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

//以下函数将一页内存页面映射到指定线性地址处,它返回页面的物理地址
//把一物理内存页面映射到线性地址空间指定处或者说把线性地址空间指定地址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) & 0xffctmp=*(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>

转载于:https://www.cnblogs.com/mengfanrong/p/3774140.html

Linux内核之内存管理(4)--缺页处理程序相关推荐

  1. Linux内核学习--内存管理模块

    Linux内核学习--内存管理模块 首先,Linux内核主要由五个部分组成,他们分别是:进程调度模块.内存管理模块.文件系统模块.进程间通信模块和网络接口模块. 本部分所讲的内存是内存管理模块,其主要 ...

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

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

  3. fork的黑科技,它到底做了个啥,源码级分析linux内核的内存管理

    最近一直在学习linux内核源码,总结一下 https://github.com/xiaozhang8tuo/linux-kernel-0.11 一份带注释的源码,学习用. fork的黑科技,它到底做 ...

  4. linux内核之内存管理.doc,linux内核之内存管理.doc

    Linux内核之内存管理 作者:harvey wang 邮箱:harvey.perfect@ 新浪博客地址:/harveyperfect ,有关于减肥和学习英语相关的博文,欢迎交流 把linux内存管 ...

  5. Linux内核中内存管理相关配置项的详细解析3

    接前一篇文章:Linux内核中内存管理相关配置项的详细解析2 5. 2:1 compression allocator (zbud) 对应配置变量为:CONFIG_ZBUD. 此项默认为选中(如果前一 ...

  6. 通过fork来剖析Linux内核的内存管理和进程管理(上)

    1.开场白 本文主要从内存管理和进程管理两个维度来窥探一下fork背后隐藏的技术细节,希望能够通过本文让大家站在一个高度去看进程创建. 全文分为两部分讲解:fork的内存管理部分和进程管理部分,内存管 ...

  7. 【Linux内核】内存管理——内存回收机制

    转载请注明: https://www.cnblogs.com/Ethan-Code/p/16626560.html 内存回收的方式 前文提到malloc的内存分配方式,malloc申请的是虚拟内存,只 ...

  8. 通过fork来剖析Linux内核的内存管理和进程管理(下)

    上一篇文章我们讲到fork的时候内存管理相关的内容,时间大概隔了快一周了,发布下篇文章,写文章确实费时费力,需要仔细推敲,原创不易,希望大家多多支持吧.本文讲解fork的时候进程管理相关的内容,主要讲 ...

  9. 从底层原理出发,了解Linux内核之内存管理

    本文讲解更加底层,基本都是从Linux内核出发,会更深入.所以当你都读完,然后再次审视这些功能的实现和设计时,我相信你会有种豁然开朗的感觉. 1.页 内核把物理页作为内存管理的基本单元. 尽管处理器的 ...

最新文章

  1. 设计模式之【抽象工厂模式】
  2. 未定义标识符 stringc/c++(20)_20款丰田酷路泽5700绝版现车最后促销
  3. 负载均衡—算法/策略
  4. 什么是SAP Commerce Cloud OCC
  5. 更轻易地实现 Jwt Token
  6. 华润置地php面试题_从一流到顶流|2020华润置地与沈阳一起美好
  7. Windows 任务栏缩略图自定义程序[更新 Build20100830]
  8. 参会邀请 - CCKS2020 | 2020全国知识图谱与语义计算大会(CCKS2020)明日开幕
  9. HBase使用场景和成功案例 (转)
  10. python-socket客户服务端的传输原理异常关闭的情况
  11. Linux的capability深入分析(2)
  12. 智能指针的释放_堆栈里的悄悄话——智能指针
  13. 盛大易宝只是陈天桥的梦而已
  14. 举例说明 频分多址FDMA、时分多址TDMA、码分多址CDMA、空分多址SDMA的异同
  15. 43款设计师必备英文设计字体【书法类字体】
  16. adreno630gpu参数_高通骁龙AdrenoGPU天梯以及直观分析,推荐。
  17. php保存文件乱码,如何解决php保存文件乱码的问题
  18. 掌握一种基本图形元素光栅化算法,利用OpenGL实现直线光栅化的DDA算法。
  19. 试题 入门训练 Fibonacci数列
  20. 人民邮电出版社专访刘遄老师:不做技术的搬运工。

热门文章

  1. 二次开发photoshop_Photoshop 101:Web开发人员简介
  2. 溢出内容菜单_停止过度使用溢出菜单
  3. 使用Wireshark进行DNS协议解析
  4. 面向对象概念及三大特点
  5. https和http有什么区别?看下面介绍就知道了!
  6. MaxCompute助力OSS支持EB级计算力
  7. 【51CTO学院三周年】遇到
  8. ubuntu安装redis的方法以及PHP安装redis扩展、CI框架sess使用redis的方法
  9. MySQL 5.5 服务器变量详解(二)
  10. 最新DynamipsGUI2.8[模拟器]发布!(中文版-英文版下载)