Linux-0.11内核源码分析系列:内存管理copy_page_tables()函数分析
来源:互联网 发布:windows重启网络服务 编辑:程序博客网 时间:2024/06/12 18:13
/* *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) */ /* * Well, here is one of the most complicated functions in mm. It * copies a range of linerar addresses by copying only the pages. * Let's hope this is bug-free, 'cause this one I don't want to debug :-) * * Note! We don't copy just any chunks of memory - addresses have to * be divisible by 4Mb (one page-directory entry), as this makes the * function easier. It's used only by fork anyway. * * NOTE 2!! When from==0 we are copying kernel space for the first * fork(). Then we DONT want to copy a full page-directory entry, as * that would lead to some serious memory waste - we just copy the * first 160 pages - 640kB. Even that is more than we need, but it * doesn't take any more memory - we don't copy-on-write in the low * 1 Mb-range, so the pages can be shared with the kernel. Thus the * special case for nr=xxxx. *//* Linus认为下面copy_page_tables()函数是内存管理部分最难的之一 * copy_page_tables()函数只被fork函数调用 * 拷贝只是拷贝了一个页表,页表是管理4M地址的,所以按照4M对齐 * 不拷贝物理页内容,当发生写时拷贝才会拷贝页表所管理的物理页内容 * 对于进程0和1,只拷贝前160页共640Kb,出于效率考虑 * 0-1M作为内核驻留地址区域,禁止写覆盖 * 参数from,to是0-4G线性地址,size是字节为单位 */int copy_page_tables(unsigned long from,unsigned long to,long size){unsigned long * from_page_table; //用于管理源页表 unsigned long * to_page_table; //用于管理目的页表unsigned long this_page; //用于保存页表unsigned long * from_dir, * to_dir; //用于管理源页目录项,目的页目录项unsigned long nr; //用于保存页表项个数if ((from&0x3fffff) || (to&0x3fffff)) //4M对齐检测,否则diepanic("copy_page_tables called with wrong alignment");from_dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */ //源页目录项to_dir = (unsigned long *) ((to>>20) & 0xffc); //目的页目录项size = ((unsigned) (size+0x3fffff)) >> 22; //页表项个数是字节数除以4Mfor( ; size-->0 ; from_dir++,to_dir++) { if (1 & *to_dir) //如果目的页目录项已经被使用,diepanic("copy_page_tables: already exist");if (!(1 & *from_dir)) continue; //如果源页目录项未使用,跳过,不拷贝from_page_table = (unsigned long *) (0xfffff000 & *from_dir);//取源页表 if (!(to_page_table = (unsigned long *) get_free_page())) return -1; /* Out of memory, see freeing */ //取空闲物理页为to_page_table赋值 //如果没有空闲物理页,die *to_dir = ((unsigned long) to_page_table) | 7; //将页表存进相应页目录项, //7表示可读写 //想一下常用的chmod 777 anyfile nr = (from==0)?0xA0:1024; //如果是0地址,只拷贝160页,否则拷贝1024页 //一个页目录表管理1024个页目录项 //一个页表管理1024个页表项 //一个页表项管理有4K物理地址 for ( ; nr-- > 0 ; from_page_table++,to_page_table++) { this_page = *from_page_table; //从源页表中取源页表项 if (!(1 & this_page)) //如果源页表项未被使用,跳过 continue; this_page &= ~2; //目的页表项读写位, //设置为只读 *to_page_table = this_page; //将源页表项存进目的页表项 if (this_page > LOW_MEM) { //如果是主内存区 *from_page_table = this_page;//源页表项也要设置为只读 this_page -= LOW_MEM; //取相对主内存的偏移地址 this_page >>= 12; //取主内存管理数组索引 mem_map[this_page]++; //物理页引用次数加1 } } } invalidate(); //刷新高速缓存 return 0; //返回0表示成功}
0 0
- Linux-0.11内核源码分析系列:内存管理copy_page_tables()函数分析
- Linux-0.11内核源码分析系列:内存管理get_free_page()函数分析
- Linux-0.11内核源码分析系列:内存管理free_page()与free_page_tables()函数分析
- Linux-0.11内核源码分析系列:内存管理get_empty_page()与put_page()函数分析
- Linux-0.11内核源码分析系列:内存管理try_to_share()与share_page()函数分析
- Linux-0.11内核源码分析系列:内存管理up_wp_page()与do_wp_page()函数分析
- 内存管理(Linux内核源码分析)
- linux内核分析-内存管理
- linux内核分析-内存管理
- linux内核分析-内存管理
- Linux内核源码分析--内存管理(二、函数实现技巧)
- Linux内核源码分析--内存管理(二、函数实现技巧)
- Linux内核源码分析--内存管理(一、分页机制)
- linux内核源码分析(内存管理)--之数据结构
- Linux内核源码分析--内存管理(一、分页机制)
- Linux-0.11内核源码分析系列:进程调度sleep_on()函数分析
- linux内核内存管理子系统概要分析
- linux内核分析笔记----内存管理
- 第13周项目1-数组大折腾(5)
- 第十三周 项目五:字符串操作(1.3)
- 在项目中使用Liquibase
- Linux中的man手册
- [JavaScript]20款最优秀的JavaScript编辑器 哪家强你说了算!
- Linux-0.11内核源码分析系列:内存管理copy_page_tables()函数分析
- Oracle 11g R2 RSF(Recurive Subquery factoring)
- ASP表单输入到HTML
- 十三周项目五
- oracle sql 优化
- 数据库的索引
- 实现java导出Excel表
- 工大培训——day5 C题 线段树变形应用
- 在Linux里设置环境变量的方法(export PATH)