2007-4-13 20:46:00 linux0.11之copy_page_tables()函数见解
好常时间没更新了,今天看了一个函数,是linux0.11的内存管理的一个重要的函数,本来该写在笔记上的,但一时兴起,就写到博客上了。
00150int copy_page_tables(unsigned long from,unsigned long to,long size)
00151 {
00152 unsigned long * from_page_table;
00153 unsigned long * to_page_table;
00154 unsigned long this_page;
00155 unsigned long * from_dir, * to_dir;
00156 unsigned long nr;
00157 //下面是判断from 和to 是否在4M的边界处
00158 if ((from&0x3fffff) || (to&0x3fffff))
00159 panic("copy_page_tables called with wrong alignment");
00151 {
00152 unsigned long * from_page_table;
00153 unsigned long * to_page_table;
00154 unsigned long this_page;
00155 unsigned long * from_dir, * to_dir;
00156 unsigned long nr;
00157 //下面是判断from 和to 是否在4M的边界处
00158 if ((from&0x3fffff) || (to&0x3fffff))
00159 panic("copy_page_tables called with wrong alignment");
//赋給from_dir 页目录表的源目录起始号 (from>>20)&oxfffc =(from>>22)<<2
00160 from_dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */
00160 from_dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */
//赋給to_dir 页目录表的目的目录起始号 (to>>20)&oxfffc =(to>>22)<<2
00161 to_dir = (unsigned long *) ((to>>20) & 0xffc);
00161 to_dir = (unsigned long *) ((to>>20) & 0xffc);
//赋給size要复制的目录表项的个数
00162 size = ((unsigned) (size+0x3fffff)) >> 22;
00162 size = ((unsigned) (size+0x3fffff)) >> 22;
//下面两个for循环是复制的开始。外层循环控制目录表项的移动,内层
//循环控制二级页表项移动,复制的内容是复制目录项和页表项
00163 for( ; size-->0 ; from_dir++,to_dir++) {
00164 if (1 & *to_dir)
00165 panic("copy_page_tables: already exist");
00166 if (!(1 & *from_dir))
00167 continue;
00163 for( ; size-->0 ; from_dir++,to_dir++) {
00164 if (1 & *to_dir)
00165 panic("copy_page_tables: already exist");
00166 if (!(1 & *from_dir))
00167 continue;
//得到目录项指向的二级页表的起始地址
00168 from_page_table = (unsigned long *) (0xfffff000 & *from_dir);
00168 from_page_table = (unsigned long *) (0xfffff000 & *from_dir);
//利用get _free_page()申请一个内存页
00169 if (!(to_page_table = (unsigned long *) get_free_page()))
00170 return -1; /* Out of memory, see freeing */
00169 if (!(to_page_table = (unsigned long *) get_free_page()))
00170 return -1; /* Out of memory, see freeing */
//设置目录表项的标志位赋給to_dir
00171 *to_dir = ((unsigned long) to_page_table) | 7;
//判断from是否是从0 开始,若是,则只需复制0xA0个页面
00171 *to_dir = ((unsigned long) to_page_table) | 7;
//判断from是否是从0 开始,若是,则只需复制0xA0个页面
00172 nr = (from==0)?0xA0:1024;
//复制每一个页表项
00173 for ( ; nr-- > 0 ; from_page_table++,to_page_table++) {
00174 this_page = *from_page_table;
00175 if (!(1 & this_page))
00176 continue;
00177 this_page &= ~2;
00178 *to_page_table = this_page;
00173 for ( ; nr-- > 0 ; from_page_table++,to_page_table++) {
00174 this_page = *from_page_table;
00175 if (!(1 & this_page))
00176 continue;
00177 this_page &= ~2;
00178 *to_page_table = this_page;
//在fork()函数中会用到,就是把每个页都设置成只读,父进程和
//子进程共享页面,当进程想写页面时,产生缺页中断,利用写时复
//制技术
00179 if (this_page > LOW_MEM) {
00180 *from_page_table = this_page;
00181 this_page -= LOW_MEM;
00182 this_page >>= 12;
00183 mem_map[this_page]++;
00184 }
00185 }
00186 }
00187 invalidate();
00188 return 0;
00189 }
00179 if (this_page > LOW_MEM) {
00180 *from_page_table = this_page;
00181 this_page -= LOW_MEM;
00182 this_page >>= 12;
00183 mem_map[this_page]++;
00184 }
00185 }
00186 }
00187 invalidate();
00188 return 0;
00189 }
这段代码复制了页表,使得一个物理内存页被两个页表项所指.
本来想做个flash的,可是无奈技术不够啊