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

//以下函数将一页内存页面映射到指定线性地址处,它返回页面的物理地址
//把一物理内存页面映射到线性地址空间指定处或者说把线性地址空间指定地址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. WPF 中如何使用第三方控件 ,可以使用WindowsFormsHost 类

    允许在 WPF 页面上承载 Windows Forms控件的元素. 命名空间:   System.Windows.Forms.Integration 程序集:   WindowsFormsIntegr ...

  2. Oracle安装时先决条件检查失败的解决方案

      Oracle安装时先决条件检查失败的解决方案 [java] 安装环境:Win7-64bit专业版,内存6G,硬盘空间足够 安装版本:Oracle Database 11g Release 2 (1 ...

  3. 【HDOJ】1914 The Stable Marriage Problem

    稳定婚姻问题,Gale-Shapley算法可解. /* 1914 */ #include <iostream> #include <sstream> #include < ...

  4. 测试darwin calendar 服务器

    cd CalDAVTester README.txt中说的明白—— QUICKSTART Edit the serverinfo.xml file to run the test against yo ...

  5. Compass被墙后如何安装安装

    今天安装 Compass 多时候发现竟然安装不了,且什么提示也没有,让人纳闷.安装代码如下: $ gem install compass 运行该段代码后发现没反应,也没有提示,后来网上查了才知道,竟然 ...

  6. poj 1159 Palindrome(dp)

    题目:http://poj.org/problem?id=1159 #include<iostream> #include<cstring> #include<cstdi ...

  7. eclipse中相同代码的高亮显示

    在eclipse中 当选中一串字符时,让其他相同字符代码都高亮显示,操作如下: windows-> preferences-> java-> Editor-> Mark Occ ...

  8. linux 下使用 cmake安装mysql

    原文地址:http://www.cppblog.com/issay789/archive/2013/01/05/196967.html 一.安装 m4 下载地址: http://files.w3pc. ...

  9. git参考书籍

    Pro GIt 简体中文版 http://iissnan.com/progit/

  10. 问题与解答 [Questions & Answers]

    您可以通过发表评论的方式提问题, 我如果有时间就会思考,  并给出答案的链接. 如果您学过Latex, 发表评论的时候请直接输入Latex公式; 反之, 请直接上传图片 (扫描.拍照.mathtype ...