#define PAGE_SIZE 4096
/* these are not to be changed without changing head.s etc */
#define LOW_MEM 0x100000
extern unsigned long HIGH_MEMORY;
#define PAGING_MEMORY (15*1024*1024)
#define PAGING_PAGES (PAGING_MEMORY>>12)
#define MAP_NR(addr) (((addr)-LOW_MEM)>>12)
#define USED 100
extern unsigned char mem_map [ PAGING_PAGES ];
#define PAGE_DIRTY 0x40
#define PAGE_ACCESSED 0x20
#define PAGE_USER 0x04
#define PAGE_RW 0x02
#define PAGE_PRESENT 0x01
截取了一部分mm.h 的内容相当重要的说。。。。
PAGE_SIZE 定义了1页内存字节书。特别注意,高速缓冲块长度是1024 byte
LOW_MEM 机器物理内存1M
PAGING_MEMORY 15M 主内存区最多15M。。。其实这里如果内存大的话就应该会相应的变(个人推论,如有错误,欢迎指正!)
PAGING_PAGE 分页后的物理内存页面数,>>12 就是除以4M,每个页面的大小是4M,于是可以算得所有的页面数
MAP_NR(addr)得到指定内存地址映射页面号
USED 页面被占用号
mem_map 数组记录的值是每一个位,对应的页被引用的次数。 这里linux 0.12 采用了bits-map的策略
mem_map 数组记录的值是每一个位,对应的页被引用的次数。 这里linux 0.12 采用了bits-map的策略
关于bitmaps可以看 MOS的第三章的 Memory Management with Bitmaps (在检索目录里面有)
http://blog.csdn.net/cinmyheart/article/details/24888847#t8
void free_page(unsigned long addr)
{
if(addr <LOW_MEM) return; //如果addr是1M的内核模块映射页,那么是不能free掉的,free无效,主动return挂掉free_page
if(addr>= HIGH_MEMORY)//我刚开始一直很纠结,不是很明白为什么HIGH_MEMORY会被定义成0这里》=0是干嘛。。。
panic("tryingto free nonexistent page");
addr-=LOW_MEM;
addr>>=12;//右移12位,那么得到addr的页面数
if(mem_map[addr]--)return;
/*我只能说这个后—太技巧了。如果当前mem_map[addr]== 0 那么这个页是个free page,if判断为假于是执行下面的语句,这时候实质上是试图free一个free page是错误的。如果mem_map[addr] >0 说明有进程占用这个page,那么返回,并-1 */
mem_map[addr]=0;
panic("tryingtofree free page");
}
void mem_init(long start_mem, long end_mem)
{
int i;
HIGH_MEMORY = end_mem;
for (i=0 ; i<PAGING_PAGES ; i++)
mem_map[i] = USED;//把所有15M主内存区的mem_map 置为USED
i = MAP_NR(start_mem);
end_mem -= start_mem;
end_mem >>= 12;//除以4M得到页数
while (end_mem-->0)
mem_map[i++]=0;//把扩展内存区的mem_map 置0,设置为空闲
}
看看这两个函数,再看看其他的内存管理的函数,这函数简直就是简单到可爱啊!
调用mem_init在main.c 里面
#define EXT_MEM_K (*(unsigned short *)0x90002)
/*系统从0x90000 开始存放系统信息,0x90002存放的就是1M之后扩展的内存容量大小 extern memory 单位是KB*/
void main(void) /* This really IS void, no error here. */
{ /* The startup routine assumes (well, ...) this */
/*
* Interrupts are still disabled. Do necessary setups, then
* enable them
*/
ROOT_DEV = ORIG_ROOT_DEV;
SWAP_DEV = ORIG_SWAP_DEV;
sprintf(term, "TERM=con%dx%d", CON_COLS, CON_ROWS);
envp[1] = term;
envp_rc[1] = term;
drive_info = DRIVE_INFO;
memory_end = (1<<20) + (EXT_MEM_K<<10);
//这里把Kb为单位的EXT_MEM_K转换成byte,把内核的1M转换成byte,于是就得到了memory_end
memory_end &= 0xfffff000;//确保边界是4M对齐的
if (memory_end > 16*1024*1024)
memory_end = 16*1024*1024;
//------------------------高速缓冲的结束,就是主内存区域的开始------------------------------------------
if (memory_end > 12*1024*1024)
buffer_memory_end = 4*1024*1024;
else if (memory_end > 6*1024*1024)
buffer_memory_end = 2*1024*1024;
else
buffer_memory_end = 1*1024*1024;
main_memory_start = buffer_memory_end;
//-------------------------------------------------------------------------------------------------------------
#ifdef RAMDISK
main_memory_start += rd_init(main_memory_start, RAMDISK*1024);
//这个rd_init不必在意,他返回的返回值始终就是第二个参数,不会变,可以具体的去看代码实现,我就不贴出来了
#endif
mem_init(main_memory_start,memory_end);//这里调用mem_init初始化memory相关设置
只贴出和mem_init 有关的一段。。。
到这里。。。终于把free_page的来龙去脉摸清楚了。。。。
只有坚实的理论基础,才能深入到实践中。。。真理啊。。。要想看得懂实际的代码,还是要有理论的基础。。。。