/*
34 * Get physical address of first (actually last :-) free page, and mark it
35 * used. If no free pages left, return 0.
36 */
unsigned long get_free_page(void)
{
register unsigned long __res asm("ax"); __asm__("std ; repne ; scasw\n\t"
"jne 1f\n\t"
"movw $1,2(%%edi)\n\t" //将对应页面的内存映像置1(使用)
"sall $12,%%ecx\n\t"   //页面数*4kb=相对LOW_MEMORY的页面起始地址
"movl %%ecx,%%edx\n\t"    //加上LOW_MEMORY形成物理起始地址
"addl %2,%%edx\n\t"       //页面实际地址给edx
"movl $1024,%%ecx\n\t"
"leal 4092(%%edx),%%edi\n\t" //将该页面的末端地址给edi
"rep ; stosl\n\t" //将edi所指内存请0
"movl %%edx,%%eax\n"
"1:"
:"=a" (__res)
:"" (),"i" (LOW_MEM),"c" (PAGING_PAGES),
"D" (mem_map+PAGING_PAGES-)
:"di","cx","dx");
return __res;
}

这段代码的作用是获取一个空闲的内存页,并且返回它的地址。

首先分析,std ; repne ;scasw 这三句的作用。首先,我们参考一下下面这这篇文章:http://blog.163.com/b____d/blog/static/7491166020099115207391/

那么,我们来分析一下这个函数里含义。首先,在这三句代码执行以前,asm已经将参数装入寄存器。即:

%1(ax=0) %2(LOW_MEM)  %3(cx=PAGING_PAGES)  %4(edi=mem_map+PAGING_PAGES-1) 。这里注意的是,参数%1 "0" (0),”0“表示使用和输出相同的寄存器。即eax。

这样,这三句话的含义就很清楚了,它的作用是从edi指代的地址搜索,如果找到0位,则返回。直到检索了PAGING_PAGES长度。

也就是说,这三句指令在mem_map[ ]数组中寻找0位,并且该0位的index存储在edx中。

疑问:系统页面长度为4096bit,为何将页面内容清0时,赋予计数器ecx的值是1024而不是4096?

答:关注这里的清零指令,rep;stosl

  STOSL指令相当于将EAX中的值保存到ES:EDI指向的地址中,若设置了EFLAGS中的方向位置位(即在STOSL指令前使用STD指令)则EDI自减4,否则(使用CLD指令)EDI自增4。

  由此可见,stosl每次将4个bit清零。因此计数器赋值1024。同理,这样是为什么edi的初始值被赋予4092而不是4095

linux源代码阅读笔记 get_free_page()代码分析的更多相关文章

  1. linux源代码阅读笔记 find_entry分析

    78 static struct buffer_head * find_entry(struct m_inode * dir, 79 const char * name, int namelen, s ...

  2. linux源代码阅读笔记 free_page_tables()分析

    /* 77 * This function frees a continuos block of page tables, as needed 78 * by 'exit()'. As does co ...

  3. linux源代码阅读笔记 linux文件系统(转)

    linux文件系统:   操作系统的文件数据除了文件实际内容外,还有非常多的属性,如文件权限(rwx)与文件属性(所有者.群组.时间参数等).   文件系统通常将这两部分数据存放在不同的块.权限属性放 ...

  4. linux源代码阅读笔记 高速缓冲区管理

    高速缓冲区是文件系统访问块设备中数据的必经要道,为了访问文件系统等块设备上的数据,内核可以每次都访问块设备,进行读写操作. 为了提高系统性能,内核在内存中开辟一个高速数据缓冲区.在Linux内核中,高 ...

  5. linux源代码阅读笔记 linux文件系统(二)

    上一篇文章说到linux文件系统中分为超级块,inode块,block块.inode块给出文件的权限,修改时间,大小等信息. 但是实际上,文件的数据是存储在block块中的.而inode块中给出了存储 ...

  6. linux源代码阅读笔记 fork和execve的区别

    1. man exec就可以知到: The exec() family of functions replaces the current process image with a new proce ...

  7. linux源代码阅读笔记 linux文件系统(三)

    当系统申请一个新的inode时.系统并不会对磁盘进行读写.它会在存储在内存的inode表(inode_table)中寻找一个空闲的位置. 如果找到了,直接返回该inode.否则要等待一个空闲的位置. ...

  8. linux源代码阅读笔记 八进制

    c语言中,众所周知,以0x开头的数是16进制数.例如 0x8FFF 然而较少使用的是八进制数.它以0开头.例如 01234

  9. CI框架源代码阅读笔记3 全局函数Common.php

    从本篇開始.将深入CI框架的内部.一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说.全局函数具有最高的载入优先权.因此大多数的框架中BootStrap ...

随机推荐

  1. "大哥,割草机借我用一下,我修整一下草坪。" ---- 谈谈this与JavaScript函数调用的不解之缘

    在写上一篇有关apply和call的博文时(闲聊JS中的apply和call),起初我还是担心大家理解起来比较困难,因为要理解apply调用方式的前提是,至少先理解在JavaScript中函数调用是什 ...

  2. 原生js实现addClass,removeClass,hasClass方法

    function hasClass(elem, cls) { cls = cls || ''; if (cls.replace(/\s/g, '').length == 0) return false ...

  3. trident 序列号问题

    在使用Storm的trident做流计算开发时,遇到一个诡异的问题: 我继承IPartitionedTridentSpout或者IOpaquePartitionedTridentSpout接口做事务型 ...

  4. The Name/Origin of Country names

    1.Puerto Rico (Spanish for "Rich Port"/富裕的港口/富港 ) 2.HongKong(Chinese for "香港")

  5. 《linux源代码包的编译安装》RHEL6

    linux下源代码包的编译安装其实没那么复杂. 我是win7系统装的虚拟机,就简单说下: 举个简单的例子: http://www.openssl.org/ 这是openssl的官网,下载openssl ...

  6. TOMCAT内存大小调整

    Tomcat本身不能直接在计算机上运行,需要依赖于硬件基础之上的操作系统和一个java虚拟机.JAVA程序启动时JVM都会分配一个初始内存和最大内存给这个应用程序.这个初始内存和最大内存在一定程度都会 ...

  7. Configuration python CGI in XAMPP in win-7

    1.After install XAMPP,we need add the path of the Mysql just find the path and add it to your sys-pa ...

  8. Oracle 动态视图6 V$PROCESS

    一.视图包含当前系统oracle运行的所有进程信息.常用于将session与进程(oracle进程,操作系统进程)之间建立联系. Column Datatype Description ADDR RA ...

  9. Allegro中板子边框不封闭导致的z-copy无法用的问题

    画一个不规则的边框,有半圆形状,导致边框不封闭,无法使用Z-COPY命令,下边是解决办法: 1 画好Outline后,选择 shape -> Compose Shape , options选项卡 ...

  10. iOS多线程编程Part 3/3 - GCD

    前两部分介绍了NSThread.NSRunLoop和NSOperation,本文聊聊2011年WWDC时推出的神器GCD.GCD: Grand Central Dispatch,是一组用于实现并发编程 ...