本店直播欧洲杯

admin · 2012-05-01

  

  这日咱们不聊的确内存统制的算法,咱们就来看看,操纵体例用甚么样的一张外,抵达了统制内存的成绩。

  咱们以 Linux 0.11 源码为例,发觉进入内核的 main 函数后未几,有如此一坨代码。

  

voidmain(void){...memory_end=(1<<20)+(EXT_MEM_K<<10);memory_end&=0xfffff000;if(memory_end>16*1024*1024)memory_end=16*1024*1024;if(memory_end>12*1024*1024)buffer_memory_end=4*1024*1024;elseif(memory_end>6*1024*1024)buffer_memory_end=2*1024*1024;elsebuffer_memory_end=1*1024*1024;main_memory_start=buffer_memory_end;mem_init(main_memory_start,memory_end);...}

 

  除了最终一行外,后面的那一大坨的效用很简略。

  实在就只是针对区别的内存巨细,树立区别的范围值而已,为了体会它,咱们全部没须要思索这么全面,就假定总内存一共就 8M 巨细吧。

  那末若是内存为 8M 巨细,memory_end 便是

  8 * 1024 * 1024

  也就只会走倒数第二个分支,那末 buffer_memory_end 就为

  2 * 1024 * 1024

  那末 main_memory_start 也为

  2 * 1024 * 1024

  你细心看看代码逻辑,看是不是如此?

  固然,你不该承细思也不妨事,上述代码践诺后,便是如下成绩罢了。

  

  你看,实在便是定了三个箭头所指向的地点的三个范围变量。的确主内存区是何如统制和分拨的,要看 mem_init 里做了甚么。

  

voidmain(void){...mem_init(main_memory_start,memory_end);...}

 

  而缓冲区是何如统制和分拨的,就要看再前面的 buffer_init 里干了甚么。

  

voidmain(void){...buffer_init(buffer_memory_end);...}

 

  可是咱们这日只看,主内存是何如统制的,很简略,放轻松。

  进入 mem_init 函数。

  

#defineLOW_MEM0x100000#definePAGING_MEMORY(15*1024*1024)#definePAGING_PAGES(PAGING_MEMORY>>12)#defineMAP_NR(addr)(((addr)-LOW_MEM)>>12)#defineUSED100staticlongHIGH_MEMORY=0;staticunsignedcharmem_map[PAGING_PAGES]={0,};//start_mem=2*1024*1024//end_mem=8*1024*1024voidmem_init(longstart_mem,longend_mem){inti;HIGH_MEMORY=end_mem;for(i=0;i<PAGING_PAGES;i++)mem_map[i]=USED;i=MAP_NR(start_mem);end_mem-=start_mem;end_mem>>=12;while(end_mem-->0)mem_map[i++]=0;}

 

  发觉也没几行,并且并无更深的手段挪用,看来是个好欺侮的手段。

  细心一看这个手段,实在折腾来折腾去,便是给一个 mem_map 数组的各个地方上赋了值,并且外现整个赋值为 USED 也便是 100,而后对此中一部份又赋值为了 0。

  赋值为 100 的部份便是 USED,也就体现内存被占用,若是再的确说是占用了 100 次,这个以后再说。剩下赋值为 0 的部份就体现未被利用,也即利用次数为零。

  是不是很简略?便是打定了一个外,记载了哪些内存被占用了,哪些内存没被占用。这便是所谓的统制,并无那末神乎其神。

  那接上去天然有两个成绩,每一个元素体现占用和未占用,这个体现的界限是众大?初始化时哪些处所是占用的,哪些处所又是未占用的?

  照旧一张图就看了然了,咱们已经假定内存统共只要 8M。

  

  能够看出,初始化竣工后,实在便是 mem_map 这个数组的每一个元素都代外一个 4K 内存能否闲暇(凿凿说是利用次数)。

  4K 内存每每叫做 1 页内存,而这类统制方法叫分页统制,便是把内存分红一页一页(4K)的单元去统制。

  1M 如下的内存这个数组索性没有记载,这里的内存是无需统制的,或许换个说法是无权统制的,也便是没有权柄请求和开释,由于这个地区是内核代码所正在的处所,不克不及被传染。

  1M 到 2M 这个区间是缓冲区,2M 是缓冲区的末尾,缓冲区的首先正在那边以后再说,这些处所不是主内存地区,是以直接标帜为 USED,发生的成绩便是无奈再被分拨了。

  2M 以上的空间是主内存地区,而主内存现在没有任何法式请求,于是初始化时悉数都是零,另日等着运用法式去请求和开释这里的内存资本。

  那运用法式何如请求内存呢?咱们本讲不开展,可是咱们简略预计一下,看看请求内存的过程当中,是何如利用 mem_map 这个构造的。

  正在 memory.c 文献中有个函数 get_free_page(),用于正在主内存区中请求一页闲暇内存页,并前往物理内存页的肇端地点。

  比方咱们正在 fork 子历程的时间,会挪用 copy_process 函数来复制历程的构造新闻,此中有一个措施便是要请求一页内存,用于寄存历程构造新闻 task_struct。

  

intcopy_process(...){structtask_struct*p;...p=(structtask_struct*)get_free_page();...}

 

  咱们看 get_free_page 的的确完成,是内联汇编代码,看不懂没关系,贯注它外面就有 mem_map 构造的利用。

  

unsignedlongget_free_page(void){registerunsignedlong__resasm("ax");__asm__("std;repne;scasb
	""jne1f
	""movb$1,1(%%edi)
	""sall$12,%%ecx
	""addl%2,%%ecx
	""movl%%ecx,%%edx
	""movl$1024,%%ecx
	""leal4092(%%edx),%%edi
	""rep;stosl
	""movl%%edx,%%eax
""1:":"=a"(__res):"0"(0),"i"(LOW_MEM),"c"(PAGING_PAGES),"D"(mem_map+PAGING_PAGES-1):"di","cx","dx");return__res;}

 

  便是遴选 mem_map 中首个闲暇页面,并标帜为已利用。

  好了,本讲就这么众,只是填写了一张大外罢了,简略吧?以后的内存请求与开释等骚操纵,悉数是随着张大外 mem_map 打交道罢了,你必然要记着它哦。

文章推荐:

2022 年中国人工智能行业发展现状与市场规模分析 市场规模超 3000 亿元

该来的总要来! 切尔西老板将彻底退出英国市场

雷神黑武士四代开售:i7搭RTX3060不到9千元

智慧城市中 5G 和物联网的未来