视窗
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懓鏁剧紓宥勭窔瀵鏁撻悩鑼槹濡炪倖鍔х€靛矂鍩€椤掍緡娈滈柡宀€鍠栭幗搴ㄥ磼濮橆剛銈梻浣筋嚃閸燁偊宕惰閸炲爼姊虹紒妯荤叆闁硅姤绮庣划鏃堫敆閸曨剛鍘介梺缁樏鍫曞箹閹扮増鐓熼幒鎶藉礉鐏炶棄绁梻浣侯攰閹活亞绮婚幋锝囩闂傚倷娴囧▔鏇㈠闯閿曞倸绠柨鐕傛嫹
闂傚倸鍊风粈渚€骞栭锔藉亱婵犲﹤鐗嗙粈鍫熺箾閹存瑥鐏柛瀣枑閵囧嫰寮介顫勃闂佺粯甯$粻鏍蓟閺囩喓绠鹃柛顭戝枛婵酣姊虹拠鍙夊攭妞ゆ泦鍡楃倒闂備焦鎮堕崕鑽ゅ緤閼恒儲娅犻柟缁樺础瑜版帗鍋傞幖娣灩濞堟鎮楀▓鍨灈闁绘牕鍚嬫穱濠囨倻閼恒儲娅嗛梺鍛婃寙閸愵亜甯楀┑鐘垫暩閸嬫盯鎮洪妸褍鍨濈€光偓閳ь剟鎳為柆宥嗗殐闁冲搫瀚皬濠电偛顕崢褔鎮洪妸鈺佸惞闁稿瞼鍋為悡娑㈡煕閹扳晛濡奸柍褜鍓濆畷鐢靛垝閺冨洢浜归柟鐑樻尵閸欏棗鈹戦悙鏉戠伇婵炲懏娲滈埀顒佺啲閹凤拷闂傚倷娴囬褍霉閻戣棄鏋侀柟闂撮檷閳ь兛鐒︾换婵嬪磻椤栨氨绉虹€规洖宕灒閻犲洤妯婂ḿ顖炴⒒娴i涓茬紒韫矙瀵敻顢楅崟顒€浠奸梺鍛婎殘閸婃垶鎯旈妸銉у€為梺鎸庣箓閹冲酣鍩涙径瀣閻庣數枪鐢爼鏌熼搹顐€块柣娑卞枤閳ь剨缍嗛崰鏍不閿濆棛绡€濠电姴鍊搁顐︽煙閺嬵偄濮傛慨濠冩そ瀹曘劍绻濋崘锝嗗缂傚倷绀侀鍡欐暜閿熺姴绠氶柛銉e妼椤曢亶鏌℃径瀣仴闁哥偑鍔戝娲箹閻愭彃濮岄梺鍛婃煥缁夊綊鏁愰悙鍝勫唨妞ゎ兙鍎遍柊锝呯暦閸洘鏅查柛娑卞幐閹枫倕鈹戦悙宸殶闁告鍥х疇婵せ鍋撴鐐叉瀹曟﹢顢欓懖鈺婃Ч婵$偑鍊栭崝鎴﹀垂濞差亝鍎婇柡鍐e亾缂佺粯绻堟慨鈧柨婵嗘閵嗘劙鏌f惔銏e闁硅姤绮屽嵄闁规壆澧楅弲鎼佹煥閻曞倹瀚�闂傚倸鍊烽懗鍫曞箠閹剧粯鍋ら柕濞炬櫅閸ㄥ倿鏌涢幇顓犮偞闁割偒浜弻鐔衡偓鐢登瑰皬闂佺粯甯掗敃銈夊煘閹达附鍋愰柛娆忣槹閹瑥鈹戦悙鍙夊櫡闁搞劌缍婂﹢渚€姊洪幐搴g畵婵☆偅鐩幆灞炬償閵婏妇鍘撻悷婊勭矒瀹曟粌鈻庨幘宕囩枃闂佸綊鍋婇崗姗€寮搁弮鍫熺厵閺夊牓绠栧顕€鏌涚€n亶鍎旈柡灞剧洴椤㈡洟濡堕崨顔锯偓鍓х磽閸屾氨袦闁稿鎹囧缁樻媴閻熸壆浜伴梺缁樺釜缁犳挻淇婇悽鍛婂€烽柣銏㈡暩椤︻垶姊洪崫鍕殭闁绘妫涢惀顏囶樄闁哄本鐩獮鍥敍濞戞哎鈧﹦绱撴担鎻掍壕闂佽法鍣﹂幏锟�闂傚倷娴囬褏鑺遍懖鈺佺筏濠电姵鐔紞鏍ь熆閼搁潧濮囬柛銊ュ€圭换婵囩節閸屾凹浼€濡炪倐鏅犻弨閬嶅Φ閸曨垰绠抽柟瀛樼箖濞堣尙绱撴担椋庤窗闁革綇绲介锝夊醇閺囩喎鈧兘鏌涢…鎴濅簼闁绘繍浜滈埞鎴︽倷閼碱剙顤€闂佹悶鍔屾晶搴e垝濮樿埖鐒肩€广儱鎳愰崝鎾⒑閸涘﹤澹冮柛娑卞灱濡差剚绻濋悽闈浶ユい锝勭矙閸┾偓妞ゆ巻鍋撻柛鐔锋健閸┾偓妞ゆ帒鍊归崵鈧梺鎸庢磸閸ㄦ椽骞忛崨鏉戠闁圭粯甯楅鍧楁⒒娴e懙褰掑嫉椤掑倹宕茬€广儱顦懜褰掓煙缂併垹鏋熼柣鎾寸懇閹鈽夊▎瀣窗婵犫拃灞藉缂佺粯绻堥崺鈧い鎺嶇劍婵挳鏌涢敂璇插箻闁硅櫕绻堝娲礈閼碱剙甯ラ梺绋款儏閹虫劗妲愰悙鍝勭劦妞ゆ帒瀚埛鎴︽煟閻旂ǹ顥嬮柟鐣屽█閺岋絽螖閸愩劋鎴烽梺鐟扮畭閸ㄥ綊锝炲┑瀣垫晞闁兼亽鍎虫禍娆撴⒒娴e憡鎯堟繛璇х畵閹矂顢欓悙顒€搴婇梺绯曞墲缁嬫帡鎮″▎鎰╀簻闁圭偓顨呴崯鐗堢閺夋埈娓婚柕鍫濇婢跺嫰鏌涢幘璺烘瀻闁伙絿鍏橀弫鎰板幢濞嗘垹妲囬梻浣告啞閸斿繘寮查埡浣勶綁顢涢悙绮规嫼闂佸ジ鈧稑宓嗛柛婵堝劋閹便劍绻濋崒銈囧悑闂佸搫鑻悧鎾荤嵁濮椻偓椤㈡瑩鎳栭埡濠傛倛闂傚倷鑳堕幊鎾绘偤閵娧冨灊鐎广儱娲ら崹婵嬫煥閺囩偛鈧綊鎮¢妷锔剧闁瑰鍊栭幋婵撹€块柣妤€鐗忕弧鈧梺閫炲苯澧存鐐茬Ч椤㈡瑩骞嗚鐟欙附绻濋悽闈涗粶婵☆偅顨呴湁濡炲娴烽悳缁樹繆閵堝懎鏆熺痪鎯с偢閺岋繝宕掑☉鍗炲妼闂佺ǹ楠哥换鎺楀焵椤掑喚娼愰柟鍝デ硅灋婵犻潧妫涢弳锔芥叏濡灝鐓愰柛瀣姉缁辨挻鎷呯拹顖滅窗閻熸粎澧楅崹鍨潖濞差亜绠伴幖绮光偓铏亞闂備胶鎳撻崵鏍箯閿燂拷闂傚倷娴囬褍霉閻戣棄鏋侀柟闂寸缁犵娀鏌熼幑鎰厫闁哄棙绮嶉妵鍕箛閸撲胶鏆犵紓浣插亾闁糕剝岣跨粻楣冩煙鐎甸晲绱虫い蹇撶墕閺嬩線鏌涢锝嗙闁稿﹦鏁搁惀顏堫敇閻愭潙顎涘┑鐐插悑閸旀瑩寮诲☉銏犖╅柨鏂垮⒔閻撲胶绱撴担绋库偓鍦暜閿熺姰鈧礁螖娴g懓顎撶紓浣割儏閺呮繈顢曢敂瑙f嫼闁荤喐鐟ョ€氼厾娆㈤懠顒傜<缂備焦锚閻忓鈧鍣崑濠囥€佸▎鎾村仼鐎光偓婵犲啰銈┑鐘愁問閸犳濡靛☉銏犵;闁瑰墽绮悡鍐喐濠婂牆绀堟繛鍡樻尭绾惧綊鏌涘┑鍕姢缂佲偓婵犲洦鍊甸柨婵嗛閺嬬喖鏌涙惔锛勑ч柡灞剧洴瀵挳濡搁妷銉х憿闁荤喐绮庢晶妤冩暜濡ゅ懏鍋傞柍褜鍓欓—鍐Χ閸℃鐟ㄩ梺鎸庢穿婵″洨鍒掗崼銉︽櫢闁跨噦鎷�闂傚倸鍊峰ù鍥ㄧ珶閸喆浠堢紒瀣儥濞兼牕鈹戦悩宕囶暡闁绘帡绠栭弻鐔虹磼閵忕姵鐏堝┑鈽嗗亝閿曘垽寮婚敐澶嬪亜缂佸顑欏Λ鍡欑磼缂併垹骞愰柛瀣崌濮婄粯鎷呴悷閭﹀殝缂備礁顑嗙敮鎺楁偩濠靛绠瑰ù锝呮憸閿涙盯姊洪崫鍕犻柛鏂块叄閵嗗懘鎮滈懞銉у弳闂佺粯娲栭崐鍦偓姘炬嫹:webmaster@jscj.com闂傚倸鍊风欢姘缚瑜嶈灋鐎光偓閸曨偆锛涢梺鐟板⒔缁垶鎮¢悢鎼炰簻妞ゆ劦鍋勯獮妯肩磼娴e搫鍘撮柡宀嬬秮閺佸倻鎹勯妸褏鍘梻浣芥〃缁€浣虹矓瑜版帒鏋侀柟鍓х帛閺呮悂鏌ㄩ悤鍌涘4008816886

相关文章

无相关信息
更新时间2022-09-16 10:07:22【至顶部↑】
联系我们 | 邮件: webmaster@jscj.com | 客服热线电话:4008816886(QQ同号) |  濠电姷鏁告慨鐑藉极閹间礁纾块柟瀵稿Х缁€濠囨煃瑜滈崜姘跺Φ閸曨垰鍗抽柛鈩冾殔椤忣亪鏌涘▎蹇曠闁哄矉缍侀獮鍥敋閸涱喗鐦滈梻浣呵归鍡涘箲閸ヮ剚鍋樻い鏇楀亾鐎规洖缍婇、娆撳矗閵壯勶紡婵犵數濮烽弫鍛婃叏椤撱垹纾婚柟鍓х帛閻撴洟鏌曟径瀣仴闁兼椿鍨伴埢鎾活敃閵忊晜瀵岄梺闈涚墕濡瑩藟閸℃ǜ浜滈柡鍌氬皡閸旂喖鏌熼獮鍨伈闁轰焦鎹囬弫鎾绘晸閿燂拷

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

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