日期:2014-05-16  浏览次数:20823 次

《linux 内核完全剖析》chapter 13 内存管理 (不含swap.c)

内存管理(memory.c 和swap.s 部分)



      “倒着看” 先看memory management,很明显,前面各种阻力,都是因为涉及内存管理。不先看这个,我估计前面看了也是白看

        我估算着理论打基础砸了差不多一个星期的时间在memory management上面了。。。感觉很有收获,是时候用实践(code)印证理论了!


《modern operating system》讲内存管理那一章

http://blog.csdn.net/cinmyheart/article/details/24888847

free_page

http://blog.csdn.net/cinmyheart/article/details/24940731

get_free_page

http://blog.csdn.net/cinmyheart/article/details/24967455

           上面两个函数单独拿出来笔记了,几乎这章memory.c 里后面的函数都会用到get_free_page,所以很重要


          由于swap page部分和块设备有关系。。。偶还木有看,swap牵扯的比较多,这章暂且不做印证,待以后更新吧



free_page_table



int free_page_tables(unsigned long from,unsigned long size)//size是页表的数目
{
	unsigned long *pg_table;
	unsigned long * dir, nr;

	if (from & 0x3fffff)//检测开始释放页的地址是否4M对齐
		panic("free_page_tables called with wrong alignment");
	if (!from)//如果 from为0 即空指针,则不允许释放。。。。很明显
		panic("Trying to free up swapper memory space");
	size = (size + 0x3fffff) >> 22;//对size进行取整的一个小技巧
	dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */ //戳这个link http://blog.csdn.net/cinmyheart/article/details/24964363
        // 下面这个循环是对页目录page  directory的循环
	for ( ; size-->0 ; dir++) {
		if (!(1 & *dir))//检测该目录项是否已经被使用,对应<注释> 743页 页目录和页表项结构最低位P的检测
			continue;//如果没有使用,就不用释放,直接跳过,进行下一个页目录的检索
		pg_table = (unsigned long *) (0xfffff000 & *dir);//对dir进行解引用,得到页表项的首地址,并且强制转换成指针,赋值给pg_table,
                                                                 //此时pg_table指向该表项的首地址
                //下面这个循环是对页表 page table的循环
		for (nr=0 ; nr<1024 ; nr++) {
			if (*pg_table) { //对表项地址解引用,得到物理地址,如果得到的物理地址不是RAM首地址0x00,那么则可以进行下一步,
                                         //否则pg_table++移动指针,进行下一个页的释放检测
				if (1 & *pg_table)//检测该页表项指向的物理内存页是否已经被使用,如果是,释放,否则swap 释放交换设备中的对应页
					free_page(0xfffff000 & *pg_table);
 				else
 					swap_free(*pg_table >> 1);
				*pg_table = 0;
			}
			pg_table++;
		}
		free_page(0xfffff000 & *dir);//释放掉页表本身占用的内存
		*dir = 0;//所有位置0,移除该页目录项!换而言之,*dir 不指向任何页表
	}
	invalidate();//刷新BTL
	return 0;
}
大笑理论和实践得到了很好的印证






       

 

         Linus说下面的copy_page_tables,这是他认为内存管理里面最难的代码,其实。。。纠结完上面的两个函数之后,暂且抛开swap不说(但是心里要明白,理论上要清楚是个什么过程),这个最难的代码也会思路很清晰的

        这段代码的主要思想就是把页目录项里面从某一个page(from)起始到某一个page(to)结束的之间所有的memory page释放掉

 

抛开《注释》 自己写注释写理解,这样我想,对于代码的理解会更好

 

copy_page_tables