linux 内核die函数,Linux-0.11内核源码分析系列:内存管理try_to_share()与share_page()函数分析...

/*

*Author  : DavidLin

*Date    : 2014-11-22pm

*Email   : linpeng1577@163.com or linpeng1577@gmail.com

*world   : the city of SZ, in China

*Ver     : 000.000.001

*history :     editor      time            do

*          1)LinPeng       2014-11-22      created this file!

*          2)

*/

/*

* try_to_share()检查进程P中地址”address"是否存在

* 如果存在且是没有被污染的页面,将该页面与当前进程共享

*

* 注意,前提条件是进程p不是当前进程,而且它们共享同样的执行文件

*/

/*

* try_to_share() checks the page at address "address" in the task "p",

* to see if it exists, and if it is clean. If so, share it with the current

* task.

*

* NOTE! This assumes we have checked that p != current, and that they

* share the same executable.

*/

static int try_to_share(unsigned long address, struct task_struct * p)

{

unsigned long from;         //管理源页表

unsigned long to;           //管理目的页表

unsigned long from_page;    //管理源页表项

unsigned long to_page;      //管理目的页表项

unsigned long phys_addr;    //管理源物理地址

from_page = to_page = ((address>>20) & 0xffc);  //获取页表地址

from_page += ((p->start_code>>20) & 0xffc);     //from_page加上进程P

//的数据段地址

//取得4G空间地址

to_page += ((current->start_code>>20) & 0xffc); //to_page加上当前进程

//的数据段地址

//取得4G空间地址

//注意:address指的是进程中0-64M的相对地址,要计算主内存区的数组偏移,

//必须加上任务代码段(数据段)的偏移地址,才可以获取4G空间偏移地址

/* is there a page-directory at from? */

from = *(unsigned long *) from_page;    //from是from_page的页目录项

//页目录项管理着页表

//即页表的值保存在页目录项中

if (!(from & 1))    //如果该目录项无效,即源页表也是无效

return 0;   //返回0,表示失败

from &= 0xfffff000; //取得源页表

from_page = from + ((address>>10) & 0xffc);  //此处from_page指向页框

//即页表内偏移地址

phys_addr = *(unsigned long *) from_page;    //取得源物理页地址

/* is the page clean and present? */

if ((phys_addr & 0x41) != 0x01)    //如果源物理页不干净或者不存在

return 0;                  //返回0表示失败

phys_addr &= 0xfffff000;

if (phys_addr >= HIGH_MEMORY || phys_addr 

return 0;    //如果源物理地址不在主内存区,返回0表示失败

to = *(unsigned long *) to_page;    //取得目的页目录项

if (!(to & 1))                      //如果目的页目录项P位无效

if (to = get_free_page())   //申请一块物理页用来保存目的页表

*(unsigned long *) to_page = to | 7;//将页表挂到页目录项

else

oom();//如果无法申请到空闲物理页,内存溢出报警,die

to &= 0xfffff000;     //取得目的页表

to_page = to + ((address>>10) & 0xffc);  //to_page等于目的页表的表内偏移

//即to_page[0--1023]中的索引值

if (1 & *(unsigned long *) to_page)  //如果目的页表项已经存在有效,die

panic("try_to_share: to_page already exists");

/* share them: write-protect */

*(unsigned long *) from_page &= ~2;  //源页表项设置为只读

*(unsigned long *) to_page = *(unsigned long *) from_page;  //共享

invalidate();            //刷新交换高速缓存

phys_addr -= LOW_MEM;

phys_addr >>= 12;

mem_map[phys_addr]++;    //主内存区相应物理页引用加1

return 1;                //返回1表示共享成功

}

/* share_page()函数试图找到一个进程,该进程可以和当前进程共享某个页面

* 参数address是当前进程中数据空间的某页面,即把数据空间的起始地址当做

* 0地址的相对地址

*

* 通过检查当前进程的executable->i_count,因为可执行文件被不同进程引用时会++1,

* 所以如果executable->i_count > 1,表示除了当前进程,还有其他进程使用该文件

* 如果上述条件成立,当前进程就试图与其他进程共享该页

*/

/*

* share_page() tries to find a process that could share a page with

* the current one. Address is the address of the wanted page relative

* to the current data space.

*

* We first check if it is at all feasible by checking executable->i_count.

* It should be >1 if there are other tasks sharing this inode.

*/

static int share_page(unsigned long address)

{

struct task_struct ** p;    //指向进程指针的指针

if (!current->executable)   //如果没有对应执行文件,返回

return 0;

if (current->executable->i_count 

return 0;                        //返回

for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {    //遍历进程管理数组

if (!*p)    //如果进程不存在,继续

continue;

if (current == *p)    //如果进程等于当前进程

continue;     //继续

if ((*p)->executable != current->executable)

continue;     //如果执行文件不同

if (try_to_share(address,*p))    //试图与找到的进程共享该页

return 1;                //返回1表示成功

}

return 0;    //如果上述无法找到进程共享页面,返回0表示失败

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值