get_free_page()

get_free_page()

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内核设计的艺术

mem_map初始化 scas(string scan instruction) stos(Store String)