Linux-0.11内核源码分析系列:内存管理try_to_share()与share_page()函数分析
2014-11-24 20:00
756 查看
/* *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) */ <pre name="code" class="plain">/* * 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 < LOW_MEM) 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 < 2) //如果只有当前进程引用该文件 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表示失败 }
相关文章推荐
- Linux-0.11内核源码分析系列:内存管理try_to_share()与share_page()函数分析
- Linux-0.11内核源码分析系列:内存管理up_wp_page()与do_wp_page()函数分析
- Linux-0.11内核源码分析系列:内存管理copy_page_tables()函数分析
- Linux-0.11内核源码分析系列:内存管理copy_page_tables()函数分析
- Linux-0.11内核源码分析系列:内存管理get_free_page()函数分析
- Linux-0.11内核源码分析系列:内存管理get_empty_page()与put_page()函数分析
- Linux-0.11内核源码分析系列:内存管理get_empty_page()与put_page()函数分析
- Linux-0.11内核源码分析系列:内存管理up_wp_page()与do_wp_page()函数分析
- Linux-0.11内核源码分析系列:内存管理free_page()与free_page_tables()函数分析
- Linux-0.11内核源码分析系列:内存管理free_page()与free_page_tables()函数分析
- Linux-0.11内核源代码分析系列:内存管理get_free_page()函数分析
- Linux-0.11内核源码分析系列:进程调度sleep_on()函数分析
- Linux-0.11内核内存管理get_free_page()函数分析
- Linux-0.11内核源码分析系列:关于线性地址,逻辑地址,物理地址的关系与区别
- linux0.11内存管理——try_to_share()
- Linux-0.11内核源码分析系列:进程调度
- 《第一篇 从linux 0.11系统初始化main.c的fork()函数调用分析内核源码》
- Linux+page+cache+里的几个函数的源码分析
- linux0.11内核源码剖析:第一篇 内存管理、memory.c
- Linux内核0.11版本sys_waitpid()函数分析