/*
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. (转)Linux概念架构的理解

    英文原文:Conceptual Architecture of the Linux Kernel 摘要 Linux kernel成功的两个原因:(1)架构设计支持大量的志愿开发者加入到开发过程中:(2 ...

  2. conditon监视器接口

    conditon监视器接口的实例对象必须通过Lock.newCondition()建立 立

  3. android 数据库的增删改查的另一种方式

    老师笔记 # 3 Android下另外一种增删改查方式         1.创建一个帮助类的对象,调用getReadableDatabase方法,返回一个SqliteDatebase对象 2.使用Sq ...

  4. redis setnx 分布式锁

    private final String RedisLockKey = "RedLock"; private final long altTimeout = 1 * 60 * 60 ...

  5. Microsoft.Xna.Framework.TitleContainer.OpenStream()

    /// <summary> /// This method opens a file using System.IO classes and the /// TitleLocation p ...

  6. Android String format 通过value 下的string.xml 文件

    <string name="format_coordinate" formatted="false">%s %d° %d\' %d\" % ...

  7. Spring MVC的启动过程

    一.概述 下面一个基本的运用springMVC的的web.xml的配置,这里要注意两个地方,一个是ContextLoadListener,一个是DispatcherServlet.web容器正是通过这 ...

  8. jquery 处理字符串 【转】

    1,去掉空格   var txt=$.trim($("txt1").val()); 2,转为数字   txtNum=Number($.trim(txt)) + 1; var thi ...

  9. DataGridView导入导出excel

    DataGridView导出到Excel #region 方法一 DateGridView导出到csv格式的Excel /// <summary> /// 导出数据到Excel.常用方法, ...

  10. Sql 临时表

    一个#是只能在当前打开滴查询窗体查询,两个#是能够在其他打开滴查询窗体查询 SELECT 'VR001839003YP' 列名1,'RO512498726DE' 列名2 INTO #临时表 UNION ...