Content #
遍历mem map[],找到主内存中(从高地址开始)第一个空闲页面 //代码路径:mm/memory.c:
#define LOW_MEM 0x100000
#define PAGING_MEMORY (15*1024*1024)
#define PAGING_PAGES (PAGING_MEMORY>>12)
unsigned long get_free_page(void)
{
register unsigned long __res asm("ax");
__asm__("std;repne;scasb\n\t" //反向扫描串(mem map[]),al(0)与di不等则
//重复(找引用对数为0的项)
"jne 1f\n\t" //找不到空闲页,跳转到1
"movb $1,1(%%edi)\n\t" //将1赋给edi + 1的位置,在mem map[]中,
//将找到0的项的引用计数置为1
"sall $12,%%ecx\n\t" // ecx算术左移12位,页的相对地址
"addl %2,%%ecx\n\t" // LOW_MEN + ecx,页的物理地址
"movl %%ecx,%%edx\n\t"
"movl $1024,%%ecx\n\t"
"leal 4092(%%edx),%%edi\n\t" //将edx + 4 KB的有效地址赋给edi
"rep;stosl\n\t" //将eax(即"0"(0))赋给edi指向的地址,目的是页面清零
"movl %%edx,%%eax\n"
"1:"
:"=a" (__res) //%0
:"0" (0), //%1:eax初始值0(用于scasb比较)
"i" (LOW_MEM), //%2:LOW_MEM
"c" (PAGING_PAGES), //%3:ecx=PAGING_PAGES(总页数)
"D" (mem_map + PAGING_PAGES-1) //%4:edi指向mem map[]的最后一个元素
:"di","cx","dx"); //第三个冒号后是程序中改变过的量
return __res;
}
From #
Linux内核设计的艺术