视窗
loading...
您现在的位置:首页 > IT认证 > Linux认证 >

Linux系统管理:linux内存分配方法总结


内存映射结构:

  1、32位地址线寻址4G的内存空间,其中0-3G为用户程序所独有,3G-4G为内核占有。

  2、struct page:整个物理内存在初始化时,每个4kb页面生成一个对应的struct page结构,这个page结构就独一无二的代表这个物理内存页面,并存放在mem_map全局数组中。

  3、段式映射:首先根据代码段选择子cs为索引,以GDT值为起始地址的段描述表中选择出对应的段描述符,随后根据段描述符的基址,本段长度,权限信息等进行校验,校验成功后。cs:offset中的32位偏移量直接与本段基址相累加,得出最终访问地址。

  0-3G与mem_map的映射方式:

  因linux中采用的段式映射为flat模式,所以从逻辑地址到线性地址没有变化。从段式出来进入页式,每个用户进程都独自拥有一个页目录表(pdt),运行时存放于CR3。  CR3(页目录) + 前10位 =>  页面表基址 + 中10位 => 页表项 + 后12位 => 物理页面地址

  3G-4G与mem_map的映射方式:

  分为三种类型:低端内存/普通内存/高端内存。

  低端内存:3G-3G+16M 用于DMA        __pa线性映射

  普通内存:3G+16M-3G+896M           __pa线性映射 (若物理内存<896M,则分界点就在3G+实际内存)

  高端内存:3G+896-4G                采用动态的分配方式

  4、高端内存(假设3G+896为高端内存起址)

  作用:访问到1G以外的物理内存空间。

  线性地址共分为三段:vmalloc段/kmap段/kmap_atomic段(针对与不同的内存分配方式)

  从内存分配函数的结构来看主要分为下面几个部分:

  a.伙伴算法(最原始的面向页的分配方式)

  alloc_pages 接口:

  struct page * alloc_page(unsigned int gfp_mask)--分配一页物理内存并返回该页物理内存的page结构指针。

  struct page * alloc_pages(unsigned int gfp_mask, unsigned int order)--分配 个连续的物理页并返回分配的第一个物理页的page结构指针。

  <释放函数:__free_page(s)>

  内核中定义:#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)

  最终都是调用 __alloc_pages. 其中MAX_ORDER 11,及最大分配到到页面个数为2^10(即4M)。

  分配页后还不能直接用,需要得到该页对应的虚拟地址:

  void *page_address(struct page *page);

  低端内存的映射方式:__va((unsigned long)(page  -  mem_map)  <<  12)

  高端内存到映射方式:struct page_address_map分配一个动态结构来管理高端内存。(内核是访问不到vma的3G以下的虚拟地址的) 具体映射由kmap / kmap_atomic执行。

  get_free_page接口:(alloc_pages接口两步的替代函数)

  unsigned long get_free_page(unsigned int gfp_mask)

  unsigned long __get_free_page(unsigned int gfp_mask)

  Unsigned long __get_free_pages(unsigned int gfp_mask, unsigned int order)

  <释放函数:free_page>

  与alloc_page(s)系列最大的区别是无法申请高端内存,因为它返回到是一个线性地址,而高端内存是需要额外映射才可以访问的。

  b.slab高速缓存(反复分配很多同一大小内存)   注:使用较少

  kmem_cache_t* xx_cache;

  创建: xx_cache = kmem_cache_create(“name”, sizeof(struct xx), SLAB_HWCACHE_ALIGN, NULL, NULL);

  分配: kmem_cache_alloc(xx_cache, GFP_KERNEL);

  释放: kmem_cache_free(xx_cache, addr);

  内存池

  mempool 不使用。

  c.kmalloc(最常用的分配接口)         注:必须小于128KB

  GFP_ATOMIC 不休眠,用于中断处理等情况

  GFP_KERNEL 会休眠,一般状况使用此标记

  GFP_USER   会休眠

  __GFP_DMA  分配DMA内存

  kmalloc/kfree

  d.vmalloc/vfree vmalloc采用高端内存预留的虚拟空间来收集内存碎片引起的不连续的物理内存页,是用于非连续物理内存分配。

  当kmalloc分配不到内存且无物理内存连续的需求时,可以使用。(优先从高端内存中查找)

  e.ioremap()/iounmap()

  ioremap()的作用是把device寄存器和内存的物理地址区域映射到内核虚拟区域,返回值为内核的虚拟地址。使用的线性地址区间也在vmmlloc段

  注:

  vmalloc()与 alloc_pages(_GFP_HIGHMEM)+kmap();前者不连续,后者只能映射一个高端内存页面

  __get_free_pages与alloc_pages(NORMAL)+page_address(); 两者完全等同

  内核地址通过 __va/__pa进行中低内存的直接映射

  高端内存采用kmap/kmap_atomic的方式来映射

  个人总结如下:

  a.在<128kB的一般内存分配时,使用kmalloc

  允许睡眠:GFP_KERNEL

  不允许睡眠:GFP_ATOMIC

  b.在>128kB的内存分配时,使用get_free_pages,获取成片页面,直接返回虚拟地址(<4M)(或alloc_pages + page_address)

  c.b失败,

  如果要求分配高端内存:alloc_pages(_GFP_HIGHMEM)+kmap(仅能映射一个页面)

  如果不要求内存连续: 则使用vmalloc进行分配逻辑连续的大块页面.(不建议)/分配速度较慢,访问速率较慢。

  d.频繁创建和销毁很多较大数据结构,使用slab.

  e.高端内存映射:

  允许睡眠:kmap              (永久映射)

  不允许睡眠:kmap_atomic      (临时映射)会覆盖以前到映射(不建议)

闂傚倷绶氬ḿ褍螞瀹€鍕;闁跨噦鎷�

闂傚倷绶氬ḿ褍螞瀹€鍕;闁跨噦鎷�

闂傚倷绶氬ḿ褍螞濞嗘挸绀夐柡鍥ュ灩閸屻劑鏌曢崼婵囧閻庢艾顭烽弻銊モ攽閸℃ê鐝旂紓浣瑰敾缂嶄線寮婚敓鐘茬妞ゆ劧瀵岄埀顒侇殜閺岀喖鎽庨崒姘ギ闂佽鍟崶褔鍞堕梺缁樻煥閹芥粎绮旈鍕厽闁绘ê寮堕幖鎰版煟鎺抽崝灞藉祫闂佺鎻粻鎴g箽闂備浇娉曢崳锕傚箯閿燂拷
闂傚倷绀侀幖顐︽偋濠婂牆绀堟繛鎴欏灪閸嬬喐銇勯弽顐沪闁绘帡绠栭弻鏇熺箾閸喖濮庨梺璇叉唉椤曆嗗絹闂佹悶鍎荤徊鑺ユ櫠閹绘崡褰掓偂鎼淬垹娈楅悗娈垮枛閻栧吋淇婇悜鑺ユ櫆闁告挆鍐帗婵犵數鍋涢悺銊у垝瀹€鈧懞閬嶆嚃閳哄嫬小婵炲鍘ч悺銊╁吹閸岀偞鐓涢柛鎰╁妼閳ь剝宕电划鏃囥亹閹烘挾鍙嗗┑鐐村灱濞呮洜鈧熬鎷�闂備浇顕уù鐑藉极閹间降鈧焦绻濋崑顖氱秺瀹曞崬螣鐠囧樊娼梻浣风串缁蹭粙寮甸鍕仼闁告鍊戞惔銊ョ倞闁挎繂鎳庨埛澶嬬箾鐎电ǹ甯堕柟铏耿閻涱喚鈧綆鍠栫粻锝嗙節婵犲倸顏柟鏋姂濮婃椽宕ㄦ繝鍐f嫻缂備礁顑嗙敮锟犲箚閸ャ劌顕遍柡澶嬪灥閸炪劑姊洪幖鐐插姌闁告柨绉归敐鐐哄冀椤儱閰e畷鍫曟晲閸涱厸鎷ゅ┑鐐差嚟閸樠囧箠濮椻偓楠炲棝宕橀鑲╊槹濡炪倖鍔戦崹娲儊閺冣偓缁绘繈濮€閿濆棛銆愰柣搴㈣壘閹芥粌危閹扮増鏅搁柨鐕傛嫹闂傚倷鑳堕幊鎾绘偤閵娾晛鍨傞柛鎰ゴ閸亪鏌熺€电ǹ小闁绘帒锕ら埞鎴︽偐閸欏鎮欏┑鐐叉噷閸ㄥ綊婀侀梺鎸庣箓濡盯鎯屾惔銊︾厓鐟滄粓宕滃▎鎾崇疇闁归偊鍏橀弸鏃堟煙鏉堥箖妾柛瀣儔閺屾盯顢曢妶鍛€剧紓鍌氱М閸嬫捇姊绘担鐟扮亰闁绘帪绠撴俊鐢告倷閻㈢數顦梺鍝勫暙閻楀棛鐥閺屾盯骞囬娑氥€婄紓浣插亾闁跨噦鎷�闂備浇顕х花鑲╁緤婵犳熬缍栧鑸靛姇閸ㄥ倹绻濇繝鍌氼伀妞も晠鏀遍妵鍕箳閹存繃娈茬紓浣风贰閸o絽顕i崼鏇熷€烽柛顭戝亝閻濐亜鈹戦悙鑼闁搞劌澧庣划姘舵焼瀹ュ懐鍔撮梺鍛婂壃閸涱垼妲繝鐢靛Х椤d粙鍩€椤掆偓閸熷潡鍩€椤掑倹鍤€闁挎洏鍨洪幏鍛村礈閹绘帗顓块梻浣呵归張顒傛崲瀹ュ鑸归柟缁㈠枟閻撴瑩鎮楀☉娆嬬細濠⒀屽墯缁绘繈鍩€椤掍焦濯撮柛锔诲幘閹虫繈姊洪崜鑼帥闁稿鎳愮槐鐐哄焵椤掑嫭鈷戦柣鐔稿閹界娀鏌eΔ鍐ㄤ户闁瑰箍鍨归~婵嬵敄閼恒儳浜欓梻浣告惈濞诧箓鎯岄鐐床闁糕剝绋掗悡娆愩亜閹炬鍟版禒鏉戭渻閵堝棙澶勯柛鎾跺枎閻g兘鏁愰崱娆戠槇闂佸憡鍔忛弲鈺佄i鐐粹拺闁奸€涘嵆閸濈儤鎱ㄦ繝鍌ょ吋闁哄苯鐗撻獮姗€顢欓懖鈺婂悈闂備胶鎳撻悺銊у垝瀹ュ洤鍨濋柨鏇炲€归悡銉︾箾閹寸倖鎴濓耿閻楀牏绡€闁逞屽墴楠炲秹顢欓幆褍瑙︽繝鐢靛仜濡霉妞嬪海鐜绘俊銈呭暟绾惧ジ鏌¢崒娑卞劌闁稿骸绻掗埀顒冾潐閹哥ǹ螞濠靛棛鏆︽慨妯垮煐閸嬫劗绱撴担璐細鐟滅増鍨垮娲箰鎼粹€虫灆闂佺懓鍤栭幏锟�闂備浇顕уù鐑藉极閹间礁绠犻柟鎹愬煐閺嗘粍銇勯幇鍓佺暠缂佲偓閸℃ḿ绠鹃柟瀵镐紳椤忓牆鏋侀柛顐f礃閸婄數鐥鐐村婵炲吋鍔欓弻娑㈠Ω閿斿墽鐓佺紓浣稿€圭敮锟犮€佸Δ浣瑰缂佸鏅濋锔解拺閻熸瑥瀚欢鑼磼缂佹ê鐏寸€殿噮鍋婇、娆撴偩瀹€濠冪カ婵犳鍠楅妵娑㈠磻閹剧粯鐓冪憸婊堝礈濞嗘挸纾归柛婵勫劤缁€濠囨倵閿濆骸鏋熼柛搴$Ч閺屾盯寮撮妸銉ョ瑢閻熸粎澧楃敮妤呮偂閳ь剙顪冮妶鍡楃瑨闁挎洩濡囩划鍫ユ晸閿燂拷闂傚倷娴囨竟鍫熴仈缁嬫娼栧┑鐘崇閻掗箖鏌熺紒銏犳灈婵☆偅锕㈤弻锝夋偄缁嬫妫嗙紒缁㈠幐閸嬫捇姊绘担鐟邦嚋缂佸甯掗悾婵嬪箹娴e摜锛涢梺鍝勭Р閸斿酣銆呴悜鑺ョ叆闁绘洖鍊圭€氾拷:webmaster@jscj.com闂傚倷绶氬ḿ褍螞瀹€鍕;闁瑰墽绮悡鐔搞亜椤愵偄骞樼紒浣哄厴閺岋綁鏁傜捄銊х厯闂佽桨绀佺粔褰掑极閹剧粯鏅搁柨鐕傛嫹4008816886

相关文章

无相关信息
更新时间2022-09-16 10:07:22【至顶部↑】
联系我们 | 邮件: webmaster@jscj.com | 客服热线电话:4008816886(QQ同号) |  婵犵數鍎戠紞鈧い鏇嗗嫭鍙忛柣鎰暯閸嬫捇鐛崹顔句痪濠电姭鍋撻柛銉戝苯娈銈嗘椤斿﹦鎹㈤敓锟�

付款方式留言簿投诉中心网站纠错二维码手机版

电话:
付款方式   |   给我留言   |   我要纠错   |   联系我们