linux内核0.11 获取第一个空闲物理内存页的函数 get_free_page函数 问题

第70行,ecx存的就是找到的第一个空闲物理页面的地址码? 注意 "c"(PAGING_PAGES)
前面#define PAGING_MEMORY (15*1024*1024)
#define PAGING_PAGES (PAGING_MEMORY >> 12)
PAGING_PAGES不就是主内存的页面总数吗?ecx怎么变成了找到的空闲页面的!!!!!
ecx存的就是找到的第一个空闲物理页面的页号吗?

问题关键在于理解以下指令:
"std ; repne ; scasb\n\t"
1、std:方向位DF置位,即DI进行自减操作。
2、repne; scasb
这两条组合指令实现循环比较。ecx初值为15*1024,al=0,di初值为&mem_map[15*1024-1],即从数组mem_map的最后一项开始,依次与al(=0)进行比较。假设数组第i项mem_map[i]==0,则结束循环,此时ecx=i, edi=&mem_map[i-1](因为ecx初值为15*1024,di初值为数组最后一项15*1024-1的地址)。找到空闲页面后,将该数组项置1,即*(edi+1)=mem_map[i]=1,即语句“movb $1,1(%%edi)”实现的功能。此时,ecx即为空闲页面索引。
几点说明:
1、rep循环结束条件:
Repeat Prefix Termination Condition 1 Termination Condition 2
REP RCX or (E)CX = 0 None
REPE/REPZ RCX or (E)CX = 0 ZF = 0
REPNE/REPNZ RCX or (E)CX = 0 ZF = 1

2、rep循环执行顺序:
WHILE CountReg ≠ 0
DO
Service pending interrupts (if any);
Execute associated string instruction; // 1、执行相关指令。例如scansb指令,除了执行al与*di的比较外,di也会被影响,即di自减1(当DF==1时)或自加1(当DF==0时)
CountReg ← (CountReg – 1); // 2、ECX自减
IF CountReg = 0 // 3、判断ECX是否已减到0
THEN exit WHILE loop; FI;
IF (Repeat prefix is REPZ or REPE) and (ZF = 0) // 4、最后才判断其他相关标志。
or (Repeat prefix is REPNZ or REPNE) and (ZF = 1)
THEN exit WHILE loop; FI;
OD;
3、scasb指令对di的影响:
After the comparison, the (E)DI register is incremented or decremented automatically according to the setting of
the DF flag in the EFLAGS register. If the DF flag is 0, the (E)DI register is incremented; if the DF flag is 1, the (E)DI
register is decremented. The register is incremented or decremented by 1 for byte operations, by 2 for word operations, and by 4 for doubleword operations.

以上指令请参考《Intel 64 and IA-32 Architectures Software Developer's Manual》。
温馨提示:内容为网友见解,仅供参考
第1个回答  2014-10-22
198 unsigned long get_free_page(void)
199{
200 unsigned long result;
201
202repeat:
203 __asm__("std ; repne ; scasb\n\t"
204 "jne 1f\n\t"
205 "movb $1,1(%%edi)\n\t"
206 "sall $12,%%ecx\n\t"
207 ...
215 :"0" (0),"i" (LOW_MEM),"c" (PAGING_PAGES),
216 "D" (mem_map+PAGING_PAGES-1)
217 :"di","cx","dx");
...
223 }
224 if (!result && swap_out())
225 goto repeat;
226 return result;
227}

在这段代码中, 没有存在中断屏蔽cli , 而在fork系统调用中直接使用这个函数, 如果在执行到204的时候被中断, 并且其他进程也调用fork系统调用执行完这个函数, 这样就会导致同一页被引用两次, 而mark数值 1 而造成数据重复的错误. 不知道会不会造成这样子的错误.本回答被网友采纳

linux内核0.11 获取第一个空闲物理内存页的函数 get_free_page函数 问题...
假设数组第i项mem_map[i]==0,则结束循环,此时ecx=i, edi=&mem_map[i-1](因为ecx初值为15*1024,di初值为数组最后一项15*1024-1的地址)。找到空闲页面后,将该数组项置1,即*(edi+1)=mem_map[i]=1,即语句“movb $1,1(%%edi)”实现的功能。此时,ecx即为空闲页面索引。几点说明...

kmallocLINUX内核中物理内存分配函数分析
在Linux内核中,内存分配主要通过kmalloc()和__get_free_page()两种函数来实现。kmalloc()主要用于小内存的连续虚拟地址分配,它基于slab机制,实际上在页分配器的基础上进行更细粒度的内存划分。通过追踪kmalloc()的实现,我们可以看到它首先调用__cache_alloc(),进而通过kmem_cache_alloc()等函数,最终...

关于Linux-0.11内核_段页内存管理的问题
Linux-0.11采用段页机制,具体如下:内存物理地址0处开始放着一页页目录表和四页页表。这一个页目录表是所有进程共享的。其后的四页页表正好映射16M物理内存,是进程0的页表。以后创建进程时页表要从主内存区申请,而页目录项直接从页目录表中取。这样进程和页目录表页存在一一对应关系,任务号为nr的...

Linux内核空间内存动态申请?
_get_free pages ()系列函数\/宏本质上是Linux内核最底层用于获取空闲内存的方法,因为底层的buddy算法以2n页为单位管理空闲内存,所以最底层的内存申请总是以2n页为单位的。get_free _pages ()系列函数\/宏包括get_zeroed _page () 、_get_free_page ()和get_free pages () 。__get_free_pages...

关于虚拟内存中页目录与页表在物理内存中加载的问题
每个页目录项有4字节,高20位储存页表的物理地址,低12位储存页表的属性。一张页表4KB,这4KB必须是连续的。但是各张页表之间不必连续。Linux创建新进程时,仅仅调用了get_free_page找到一页空内存,把进程页表塞进去而已。页表不能被普通进程直接访问。访问用户区虚拟地址是看不到进程页表的。内核的页表...

通过do_execve源码分析程序的执行(上)(基于linux0.11)
完成物理地址映射后,内存布局随之调整。紧接着,通过create_tables函数分配执行环境变量和参数的数组。执行完毕后,内存布局进一步调整。最后,设置栈、堆位置,以及eip为执行文件头部指定值,esp为当前栈位置,至此,可执行文件加载阶段完成。下文将探讨执行第一条指令后的后续步骤。

常用linux命令下的free命令
free命令可以显示Linux系统中空闲的、已用的物理内存及swap内存,及被内核使用的buffer。在Linux系统监控的工具中,free命令是最经常使用的命令之一。1.命令格式:free [参数]2.命令功能:free 命令显示系统使用和空闲的内存情况,包括物理内存、交互区内存(swap)和内核缓冲区内存。共享内存将被忽略3.命令参数:-b 以Byte...

【内存】ARM64的内核地址空间布局
kmalloc()和__get_free_page()等内存分配函数从normal直接映射区获取内核空间,这里的内存地址是内核态虚拟地址,实际读写的是物理内存。vmemmap区域位于线性映射区域之前,用于存储稀疏内存的page结构体数组。PCI I\/O区域则是PCI设备的I\/O地址空间,长度固定为16MB。固定映射区域是编译时预设的特殊地址,...

看懂Linux页面回收
2. 内存回收的触发基于zone的watermark值,当分配内存失败,watermark达到一定阈值时,内存回收就会启动。内存分配流程中,get_page_from_freelist和__alloc_pages_slowpath函数都会引发内存回收。3. 回收过程涉及多个函数,如直接内存回收的_perform_reclaim和try_to_free_pages。kswapd内核线程在空闲页面不足...

看懂Linux页面回收
页面回收是以zone为单位进行的,系统根据watermark来判断一个zone是否需要进行内存回收。当分配内存时,发现水位不满足要求时,就会触发内存回收。内存分配流程中,get_page_from_freelist()函数是快速分配路径的入口,__alloc_pages_slowpath()函数是慢速分配路径的入口。两个路径都会触发内存的回收。接下来...

相似回答