free_page_tables函数
本文参考地址:
1. https://blog.csdn.net/jjavaa/article/details/8115664
2. linux-0.11源码
//// 根据指定的线性地址和限长(页表个数),释放对应内存页表指定的内存块并置表项为
// 空闲。页目录位于物理地址0开始处,共1024项,每项4字节,共占4K字节。每个目录项
// 指定一个页表。内核页表从物理地址0x1000处开始(紧接着目录空间),共4个页表。每
// 个页表有1024项,每项4字节。因此占4K(1页)内存。各进程(除了在内核代码中的进
// 程0和1)的页表所占据的页面在进程被创建时由内核为其主内存区申请得到。每个页表
// 项对应1页物理内存,因此一个页表最多可映射4MB的物理内存。
// 参数:from - 起始线性基地址;size - 释放的字节长度。
1 int free_page_tables(unsigned long from,unsigned long size) 2 { 3 unsigned long *pg_table; 4 unsigned long * dir, nr; 5 6 // 首先检测参数from给出的线性基地址是否在4MB的边界处。因为该函数只能处理这 7 // 种情况。若from=0,则出错。说明视图释放内核和缓冲所占空间。 8 if (from & 0x3fffff) 9 panic("free_page_tables called with wrong alignment"); 10 if (!from) 11 panic("Trying to free up swapper memory space"); 12 // 然后计算参数size给出的长度所占的页目录项数(4MB的进位整数倍),也即所占 13 // 页表数。因为1个页表可管理4MB物理内存,所以这里用右移22位的方式把需要复制 14 // 的内存长度值除以4MB.其中加上0x3fffff(即4MB-1)用于得到进位整数倍结果,即 15 // 除操作若有余数则进1。例如,如果原size=4.01Mb,那么可得到结果size=2。 20 size = (size + 0x3fffff) >> 22;
//计算给定的线性级地震对应的实际目录项。对应的目录项号=from>>2。由于每项占4字节。且页目录表从物理地址0开始存放因而实际页目录项指针=目录项<<2(即form >>20)
//0xffc确保目录项制作范围有效。因为只移动了20位,因此最后2位页表项索引的内容,应屏蔽掉 21 dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */ 22 // 此时size是释放的页表个数,即页目录项数,而dir是起始目录项指针。现在开始 23 // 循环操作页目录项,依次释放每个页表中的页表项。如果当前目录项无效(P位=0) 24 // 表示该目录项没有使用(对应的页表不存在),则继续处理下一个目录项。否则从目 25 // 录项总取出页表地址pg_table,并对该页表中的1024个表项进行处理。释放有效页 26 // 表项(P位=1)对应的物理内存页表。然后该页表项清零,并继续处理下一页表项。 27 // 当一个页表所有表项都处理完毕就释放该页表自身占据的内存页面,并继续处理下 28 // 一页目录项。最后刷新也页变换高速缓冲,并返回0. 29 for ( ; size-->0 ; dir++) { 30 if (!(1 & *dir)) //当前目录项无效,则继续查找,参考下图 31 continue;
32 pg_table = (unsigned long *) (0xfffff000 & *dir); // 取页表地址 33 for (nr=0 ; nr<1024 ; nr++) { 34 if (1 & *pg_table) // 若该项有效,则释放对应页。 35 free_page(0xfffff000 & *pg_table); 36 *pg_table = 0; // 该页表项内容清零。 37 pg_table++; // 指向页表中下一项。 38 } 39 free_page(0xfffff000 & *dir); // 释放该页表所占内存页面。 40 *dir = 0; // 对应页表的目录项清零 41 } 42 invalidate(); // 刷新页变换高速缓冲。 43 return 0; 44 }



浙公网安备 33010602011771号