free_page()释放物理地址addr处的一页内存
本帖最后由 Gen216ius 于 2011-8-14 21:26 编辑 具体解读对着图片看,图片的英文就是代码的变量,注意这里的from是线性地址 int free_page_tables (unsigned long from, unsigned long size) { unsigned long *pg_table; unsigned long *dir, nr; if (from & 0x3fffff)// 要释放内存块的地址需以4M 为边界。 panic ("free_page_tables called with wrong alignment"); if (!from)// 出错,试图释放内核和缓冲所占空间。 panic ("Trying to free up swapper memory space"); // 计算所占页目录项数(4M 的进位整数倍),也即所占页表数。 size = (size + 0x3fffff) >> 22;//size转换为4M的倍数,此时size为个页目录项的个数 // 下面一句计算起始目录项。对应的目录项号=from>>22,因每项占4 字节,并且由于页目录是从物理地址0 开始,因此实际的目录项指针=目录项号<<2,也即(from>>20)。与上0xffc 确保目录项指针范围有效。 dir = (unsigned long *) ((from >> 20) & 0xffc); /* _pg_dir = 0 */ for (; size-- > 0; dir++){// size 现在是需要被释放内存的目录项数。 if (!(1 & *dir)) // 如果该目录项无效(P 位=0),则继续。对着下图看 continue; // 目录项的位0(P 位)表示对应页表是否存在。 pg_table = (unsigned long *) (0xfffff000 & *dir); // 取目录项中页表地址。 for (nr = 0; nr < 1024; nr++){ // 每个页表有1024 个页项。 if (1 & *pg_table) // 若该页表项有效(P 位=1),则释放对应内存页。 free_page (0xfffff000 & *pg_table); *pg_table = 0; // 该页表项内容清零。 pg_table++; // 指向页表中下一项。 } free_page(0xfffff000 & *dir);// 释放该页表所占内存页面。但由于页表在物理地址1M以内,所以这句什么都不做。 *dir = 0; // 对相应页表的目录项清零。 } invalidate (); // 刷新页变换高速缓冲。 return 0; } |