国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

剖析Buddy算法中內(nèi)存的申請(qǐng)和釋放

原創(chuàng) 精選
存儲(chǔ) 存儲(chǔ)軟件
內(nèi)存的合理利用一直是系統(tǒng)的頭等大事。目前系統(tǒng)中,除了采用Buddy和slab管理內(nèi)存外,還會(huì)采用內(nèi)存水線檢測(cè)處理,PCP機(jī)制,CMA機(jī)制等進(jìn)行內(nèi)存的優(yōu)化。在本文中,我們將從Buddy算法中內(nèi)存的申請(qǐng)和釋放,來(lái)探索內(nèi)存的奧秘。

作者 | 趙青窕

審校 | 孫淑娟

內(nèi)存的合理利用一直是系統(tǒng)的頭等大事。目前系統(tǒng)中,除了采用Buddy和slab管理內(nèi)存外,還會(huì)采用內(nèi)存水線檢測(cè)處理,PCP機(jī)制,CMA機(jī)制等進(jìn)行內(nèi)存的優(yōu)化。在本文中,我們將從Buddy算法中內(nèi)存的申請(qǐng)和釋放,來(lái)探索內(nèi)存的奧秘。

基本概念

zone:有的地方把zone稱為管理區(qū),每個(gè)node下會(huì)劃分成不同的zone。有的系統(tǒng)會(huì)劃分成3個(gè)zone區(qū),有的會(huì)劃分成2個(gè)zone區(qū)。zone區(qū)的個(gè)數(shù)會(huì)因平臺(tái),內(nèi)核,系統(tǒng)的位數(shù)等有差異。

free_area:每個(gè)zone區(qū)根據(jù)2的order次方(order的范圍從0到MAX_ORDER)進(jìn)一步劃分,劃分后的每個(gè)小區(qū)域通過(guò)free_area[order]表示。

如下圖紅色方框中所示,按照紅色方框從左到右分別是node,zone和free_area。

水線:每個(gè)zone存在三個(gè)水線,若當(dāng)前zone中空閑頁(yè)高于WMARK_HIGH,則當(dāng)前zone區(qū)的空閑內(nèi)存較多;若空閑頁(yè)低于WMARK_LOW,則交換守護(hù)進(jìn)程開(kāi)始將內(nèi)存交換到磁盤上;若空閑頁(yè)低于WMARK_MIN,則內(nèi)存回收系統(tǒng)還需要大量回收內(nèi)存。

order:每個(gè)zone區(qū)根據(jù)order,把內(nèi)存按照2的order繼續(xù)劃分為不同的area。

PCP鏈表:該鏈表中的每一個(gè)成員大小均是2的0次方個(gè)頁(yè)面,每次申請(qǐng)和釋放1個(gè)頁(yè)面,都會(huì)優(yōu)先考慮PCP。當(dāng)PCP為空時(shí),會(huì)從Buddy中申請(qǐng);當(dāng)PCP中頁(yè)面比較多,超過(guò)限制時(shí),會(huì)把頁(yè)面釋放到Buddy中。 

內(nèi)存申請(qǐng)

比較常用的內(nèi)存申請(qǐng)函數(shù)是kmalloc,當(dāng)申請(qǐng)的內(nèi)存大于KMALLOC_MAX_CACHE_SIZE時(shí),會(huì)通過(guò)函數(shù)kmalloc_large從Buddy中申請(qǐng)內(nèi)存,否則從slab中申請(qǐng)內(nèi)存。本文中暫不分析從slab申請(qǐng)內(nèi)存的情況。

kmalloc_large函數(shù)實(shí)現(xiàn)如下,Buddy算法中,內(nèi)存的分配和釋放均離不開(kāi)order,我們可以看到,在該函數(shù)內(nèi)部通過(guò)size來(lái)計(jì)算出對(duì)應(yīng)的order,就很好地把Buddy和slab連接在一起了。

static __always_inline void *kmalloc_large(size_t size, gfp_t flags)
{
unsigned int order = get_order(size);
return kmalloc_order_trace(size, flags, order);
}

函數(shù)kmalloc_order_trace會(huì)調(diào)用函數(shù)alloc_pages,進(jìn)而調(diào)用函數(shù)struct page *__alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, int preferred_nid, nodemask_t *nodemask)來(lái)實(shí)現(xiàn)內(nèi)存的分配。實(shí)際上,Buddy提供的對(duì)外申請(qǐng)內(nèi)存函數(shù)是alloc_pages,但其內(nèi)部實(shí)現(xiàn)大部分情況下均是通過(guò)__alloc_pages_nodemask來(lái)實(shí)現(xiàn)。該函數(shù)分三步進(jìn)行處理,分別如下:

  • 構(gòu)建內(nèi)存分配的上下文結(jié)構(gòu),內(nèi)核中采用結(jié)構(gòu)體struct alloc_context來(lái)表示
  • 快速分配
  • 慢速分配

1.內(nèi)存分配上下文結(jié)構(gòu)

內(nèi)存分析上下文采用結(jié)構(gòu)體struct alloc_context來(lái)表示,其結(jié)構(gòu)體定義如下:

/*
* Structure for holding the mostly immutable allocation parameters passed
* between functions involved in allocations, including the alloc_pages*
* family of functions.
*
* nodemask, migratetype and high_zoneidx are initialized only once in
* __alloc_pages_nodemask() and then never change.
*
* zonelist, preferred_zone and classzone_idx are set first in
* __alloc_pages_nodemask() for the fast path, and might be later changed
* in __alloc_pages_slowpath(). All other functions pass the whole strucure
* by a const pointer.
*/
struct alloc_context {
struct zonelist *zonelist;
nodemask_t *nodemask;
struct zoneref *preferred_zoneref;
int migratetype;
enum zone_type high_zoneidx;
bool spread_dirty_pages;
};

各個(gè)成員含義如下:

  • zonelist:用于分配內(nèi)存的zone區(qū)列鏈表。在內(nèi)存分配時(shí),內(nèi)核會(huì)通過(guò)函數(shù)numa_node_id()來(lái)獲取當(dāng)前CPU的NUMA ID,進(jìn)而根據(jù)這個(gè)ID號(hào)獲取對(duì)應(yīng)的zonelist。內(nèi)存的分配實(shí)際上就是在zonelist找合適的內(nèi)存進(jìn)行分配,該成員在后面兩步中具有關(guān)鍵作用;
  • nodemask:用來(lái)指定從哪一個(gè)node中進(jìn)行內(nèi)存分配。若沒(méi)有指定,則會(huì)在所有節(jié)點(diǎn)中嘗試分配,通常情況下該值為NULL;
  • high_zoneidx:該成員從字面意思看就是最高的zone區(qū)id號(hào),其實(shí)它表示的是在分配時(shí),所能分配的最高zone區(qū)。通常一般是從HIGH區(qū)---->NORMAL---->DMA的方式進(jìn)行分配。內(nèi)存的需求方在請(qǐng)求進(jìn)行內(nèi)存分配時(shí),會(huì)通過(guò)gfp_mask來(lái)對(duì)該成員進(jìn)行設(shè)置,Buddy在內(nèi)存分配及逆行內(nèi)存分配時(shí)需要通過(guò)函數(shù)gfp_zone(gfp_mask)來(lái)提取gfp_mask中對(duì)應(yīng)的high_zoneidx;
  • migratetype:該成員指明了需要內(nèi)存的頁(yè)面遷移類型。Buddy進(jìn)行內(nèi)存分配時(shí)需要通過(guò)函數(shù)gfpflags_to_migratetype(gfp_mask)來(lái)獲取內(nèi)存請(qǐng)求方的具體需求;
  • preferred_zone:結(jié)合成員high_zoneidx和zonelist,計(jì)算出首先從那個(gè)zone區(qū)開(kāi)始進(jìn)行內(nèi)存的分配,即第一個(gè)將要被遍歷的zone,內(nèi)核中是通過(guò)函數(shù)first_zones_zonelist來(lái)計(jì)算該成員的;
  • spread_dirty_pages:當(dāng)申請(qǐng)內(nèi)存時(shí),采用了標(biāo)志__GFP_WRITE,則說(shuō)明此次申請(qǐng)的物理頁(yè)面將會(huì)生成臟頁(yè),內(nèi)核中就是通過(guò)語(yǔ)句ac->spread_dirty_pages = (gfp_mask & __GFP_WRITE)來(lái)設(shè)置該成員的。

從上面的結(jié)構(gòu)體struct alloc_context的說(shuō)明可以看出,該結(jié)構(gòu)體具體細(xì)化了內(nèi)存分配的各種需求,其具體實(shí)現(xiàn)如下圖中紅色方框所示:

2.快速分配

在完成第一步后,就可以通過(guò)函數(shù)get_page_from_freelist進(jìn)行一次快速分配。該函數(shù)才是內(nèi)存分配真正的開(kāi)始位置,接下來(lái)我將詳細(xì)說(shuō)明該過(guò)程,為了簡(jiǎn)化描述,同時(shí)為了讓大家容易理解,暫時(shí)不考慮CPUSET的情況。

該函數(shù)本質(zhì)就是從preferred_zone開(kāi)始,遍歷zonelist,其每一次遍歷時(shí),處理流程如下:

  • 臟頁(yè)面判斷

每個(gè)node節(jié)點(diǎn)會(huì)對(duì)臟頁(yè)數(shù)進(jìn)行限制,當(dāng)超過(guò)限制后,將無(wú)法申請(qǐng)具有__GFP_WRITE標(biāo)志的內(nèi)存塊,需要跳出當(dāng)前zone區(qū),轉(zhuǎn)而掃描下一個(gè)zone區(qū),其內(nèi)核處理代碼如下圖所示,圖中進(jìn)行了標(biāo)注,方便大家理解。

  • 水位處理

前面小節(jié)中有提到每個(gè)zone中存在三個(gè)水線,在內(nèi)存申請(qǐng)時(shí),默認(rèn)采用WMARK_LOW,使用函數(shù)zone_watermark_fast進(jìn)行水線判斷。

假如通過(guò)水線檢測(cè),發(fā)現(xiàn)內(nèi)存不夠,則會(huì)判斷當(dāng)前申請(qǐng)內(nèi)存的請(qǐng)求是否采用ALLOC_NO_WATERMARKS,若采用,則說(shuō)明當(dāng)前剩余內(nèi)存多少與當(dāng)前申請(qǐng)沒(méi)有任何關(guān)系,會(huì)調(diào)用rmqueue進(jìn)行內(nèi)存分配;若沒(méi)有ALLOC_NO_WATERMARKS聲明,則進(jìn)行下一步reclaim操作;

假如通過(guò)水線檢測(cè),發(fā)現(xiàn)當(dāng)前還有足夠內(nèi)存,則調(diào)用函數(shù)rmqueue進(jìn)行內(nèi)存分配。

  • reclaim操作

reclaim操作首先是通過(guò)函數(shù)zone_allows_reclaim來(lái)判斷當(dāng)前的node是否支撐reclaim操作,如果不支持,就退出當(dāng)前循環(huán),執(zhí)行下一個(gè)循環(huán)操作;若支持,就調(diào)用node_reclaim執(zhí)行內(nèi)存回收的工作。

當(dāng)函數(shù)node_reclaim返回值是NODE_RECLAIM_NOSCAN或者NODE_RECLAIM_FULL時(shí),表示當(dāng)前雖然內(nèi)存不夠,但我無(wú)能為力了。這種情況下,只能退出循環(huán),執(zhí)行下一個(gè)操作;當(dāng)返回值是其余的情況時(shí),就會(huì)重新進(jìn)行水位檢測(cè),若此時(shí)內(nèi)存足夠,則調(diào)用rmqueue進(jìn)行內(nèi)存分配,否則退出循環(huán),執(zhí)行下一個(gè)循環(huán)操作。

假如當(dāng)前系統(tǒng)使用的是非NUMA,則不會(huì)進(jìn)行reclaim操作,當(dāng)水位線檢測(cè)發(fā)現(xiàn)內(nèi)存不夠時(shí),會(huì)跳出循環(huán),嘗試下一個(gè)zone;假如當(dāng)前系統(tǒng)是NUMA,才會(huì)進(jìn)行上述描述中的判斷,來(lái)決定是否進(jìn)行內(nèi)存回收。

  • rmqueue內(nèi)存分配處理

在內(nèi)存分配時(shí),分兩種情況進(jìn)行處理,分別是order = 0及order != 0。

當(dāng)order = 0時(shí),會(huì)首先從PCP鏈表中進(jìn)行內(nèi)存申請(qǐng),其具體流程如下:

當(dāng)order != 0,即要申請(qǐng)多頁(yè),下面是其處理過(guò)程,根據(jù)實(shí)際情況調(diào)用__rmqueue_smallest,__rmqueue_cma或者_(dá)_rmqueue進(jìn)行內(nèi)存的分配。

對(duì)于設(shè)置了ALLOC_HARDER的情況,先嘗試通過(guò)函數(shù)__rmqueue_smallest來(lái)分配MIGRATE_HIGHATOMIC類型的內(nèi)存塊,具體實(shí)現(xiàn)就是從zone->free_area[order]中根據(jù)需要的內(nèi)存類型進(jìn)行分配。該函數(shù)實(shí)現(xiàn)比較簡(jiǎn)單,就是遍歷free_area以便找到合適的內(nèi)存塊,下圖是__rmqueue_smallest的實(shí)現(xiàn),增加了注釋方便大家理解。

假如通過(guò)上面的__rmqueue_smallest沒(méi)有找到合適的內(nèi)存塊,在申請(qǐng)內(nèi)存時(shí),使用標(biāo)志__GFP_CMA申請(qǐng)的MIGRATE_MOVABLE,則再次使用函數(shù)__rmqueue_cma申請(qǐng)內(nèi)存,實(shí)際上__rmqueue_cma內(nèi)部是調(diào)用__rmqueue_smallest(zone, order, MIGRATE_CMA)實(shí)現(xiàn)的。

若上面的兩步__rmqueue_smallest,__rmqueue_cma均失敗,則會(huì)調(diào)用__rmqueue。該函數(shù)內(nèi)部實(shí)際上也是通過(guò)__rmqueue_smallest實(shí)現(xiàn)的,當(dāng)__rmqueue_smallest只會(huì)從指定的migtatetype中進(jìn)行分配,當(dāng)分配失敗后,會(huì)通過(guò)函數(shù)__rmqueue_fallback從后備fallbacks中找到一個(gè)遷移類型頁(yè)塊,將其遷移到目標(biāo)遷移類型中后重新進(jìn)行分配。

至此快速分配結(jié)束,若已經(jīng)分配到內(nèi)存,則會(huì)退出分配流程,否則進(jìn)行下一步操作:慢速分配。

3.慢速分配

慢速分配是通過(guò)函數(shù)__alloc_pages_slowpath來(lái)實(shí)現(xiàn)的。從快速分配發(fā)現(xiàn)無(wú)法分配到需要的內(nèi)存,緊接著內(nèi)核通過(guò)慢速分配對(duì)內(nèi)存進(jìn)行整理,嘗試找到合適的內(nèi)存。其整理過(guò)程包含:

  • 重新計(jì)算內(nèi)存分配上下文;
  • 如果設(shè)置了__GFP_KSWAPD_RECLAIM,則會(huì)調(diào)用函數(shù)wake_all_kswapds來(lái)喚醒負(fù)責(zé)換出內(nèi)存頁(yè)的守護(hù)進(jìn)程kswapds;
  • 因更新了內(nèi)存分配上下文,因此再次使用快速分配嘗試內(nèi)存分配。若分配成功,則退出本次分配;否則繼續(xù)進(jìn)行下一步操作;
  • 若申請(qǐng)內(nèi)存時(shí),設(shè)置了__GFP_DIRECT_RECLAIM,且非pfmemalloc情況下,會(huì)通過(guò)函數(shù)__alloc_pages_direct_compact進(jìn)行內(nèi)存壓縮后,再次嘗試分配頁(yè)面。若分配成功則退出;否則進(jìn)入下一步;
  • 接下來(lái)的操作代碼中采用了retry代碼標(biāo)簽,這個(gè)過(guò)程比較繁瑣,其本質(zhì)就是采用各種內(nèi)存優(yōu)化手段盡量促使本次分配成功,優(yōu)化手段主要有以下四種:
  • 通過(guò)函數(shù)__alloc_pages_direct_reclaim嘗試進(jìn)行內(nèi)存回收后,再分配內(nèi)存;
  • 通過(guò)函數(shù)__alloc_pages_direct_compact嘗試進(jìn)行內(nèi)存整合后,再分配內(nèi)存;
  • 通過(guò)函數(shù)__alloc_pages_may_oom嘗試殺掉一些優(yōu)先級(jí)不高的進(jìn)程后,再分配內(nèi)存;
  • 在retry過(guò)程中,仍會(huì)調(diào)用wake_all_kswapds來(lái)喚醒kswapds,防止意外休眠。

這四種方式都會(huì)伴隨著調(diào)用函數(shù)get_page_from_freelist來(lái)進(jìn)行內(nèi)存分配。

至此內(nèi)存分配函數(shù)就完成了。從上面的描述可以看出,當(dāng)內(nèi)存足夠時(shí),通常情況下快速分配就足夠了。只有在內(nèi)存不夠時(shí),會(huì)進(jìn)行慢速分配,慢速分配里面進(jìn)行內(nèi)存回收,整理等操作后再進(jìn)行分配。若此時(shí)還沒(méi)有足夠的內(nèi)存可以分配,說(shuō)明內(nèi)存耗盡,可能是因?yàn)閮?nèi)存泄漏導(dǎo)致內(nèi)存不足,這個(gè)時(shí)候就需要去定位內(nèi)存泄漏問(wèn)題了。

內(nèi)存釋放

Buddy中內(nèi)存釋放入口函數(shù)是free_pages。該函數(shù)的實(shí)現(xiàn)如下,從下面的函數(shù)中可以看出最后是通過(guò)free_unref_page或者_(dá)_free_pages_ok來(lái)實(shí)現(xiàn)的,其余的部分均合法性判斷。

void free_pages(unsigned long addr, unsigned int order)
{
if (addr != 0) {
VM_BUG_ON(!virt_addr_valid((void *)addr));
__free_pages(virt_to_page((void *)addr), order);
}
}

void __free_pages(struct page *page, unsigned int order)
{
if (put_page_testzero(page))
free_the_page(page, order);
}

static inline void free_the_page(struct page *page, unsigned int order)
{
if (order == 0) /* Via pcp? */
free_unref_page(page);
else
__free_pages_ok(page, order);
}

函數(shù)free_pages 接受兩個(gè)參數(shù),分別是虛擬地址和需要釋放的頁(yè)面數(shù),該函數(shù)內(nèi)部利用virt_to_page把虛擬地址轉(zhuǎn)化成Buddy算法需要的struct page結(jié)構(gòu)體。

__free_pages函數(shù)先將對(duì)應(yīng)的struct page->_refcount 減去1,之后檢測(cè)_refcount是否為0,若為0,繼續(xù)進(jìn)行釋放操作,否則不進(jìn)行內(nèi)存釋放操作。通過(guò)該函數(shù)__free_pages可以看到,不管是否進(jìn)行了內(nèi)存釋放操作,該函數(shù)都可以正常退出且沒(méi)有返回值。假如內(nèi)存釋放操作異常,就會(huì)引發(fā)內(nèi)存泄漏問(wèn)題,且代碼中沒(méi)有任何日志和錯(cuò)誤碼,這種泄漏通常很難排查。

free_the_page是真正的內(nèi)存釋放函數(shù),該函數(shù)根據(jù)order的不同,分別進(jìn)行兩種不同的處理:

  • order為0的情況
  • order不為0的情況

接下來(lái)我們分別來(lái)了解這兩種情況的處理方式。

1.order為0的情況

函數(shù)內(nèi)存會(huì)根據(jù)order是否為0來(lái)進(jìn)行相應(yīng)的操作,對(duì)于order = 0的情況,此處是調(diào)用函數(shù)free_unref_page。有些內(nèi)核中會(huì)調(diào)用函數(shù)free_hot_cold_page(page, false)來(lái)實(shí)現(xiàn),但不管調(diào)用哪一個(gè)函數(shù),其內(nèi)部均是進(jìn)行相應(yīng)的判斷后,通過(guò)把page插入PCP鏈表相應(yīng)位置處實(shí)現(xiàn)。實(shí)際上內(nèi)核在把內(nèi)存釋放到PCP鏈表時(shí),會(huì)進(jìn)行PCP鏈表成員個(gè)數(shù)pcp->count的判斷,當(dāng)pcp->count >= pcp->high時(shí),會(huì)調(diào)用函數(shù)free_pcppages_bulk釋放一部分PCP中的頁(yè)面到 Buddy 子系統(tǒng)中。

此處我們需要注意,并不是所有order = 0的內(nèi)存全部釋放到PCP鏈表中,在結(jié)構(gòu)體struct page中有個(gè)成員index,該成員指明了該部分內(nèi)存的類型,若類型為MIGRATE_ISOLATE,則其內(nèi)存(實(shí)際上是一個(gè)頁(yè)面)會(huì)釋放到Buddy中,若類型對(duì)應(yīng)的數(shù)據(jù)大于或等于MIGRATE_PCPTYPES,則釋放到類型為MIGRATE_MOVABLE的PCP鏈表中,其余的釋放到對(duì)應(yīng)類型的PCP鏈表中。下圖是order = 0時(shí)的核心處理代碼,圖中已經(jīng)標(biāo)注了各個(gè)關(guān)鍵地方,供大家參考。

2.order不為0的情況

當(dāng)order不為0時(shí),會(huì)通過(guò)函數(shù)__free_pages_ok調(diào)用free_one_page來(lái)實(shí)現(xiàn)。其核心代碼如下圖所示,圖中對(duì)代碼進(jìn)行了標(biāo)注,從其代碼我們可以發(fā)現(xiàn)其實(shí)現(xiàn)是通過(guò)while循環(huán)來(lái)查找可以合并的頁(yè)塊,查找的方式就是按照order的次序挨個(gè)查找,其整個(gè)流程就是查找--->確認(rèn)--->刪除--->合并。

此時(shí),我們來(lái)思考一個(gè)問(wèn)題,有些特殊內(nèi)存區(qū)是無(wú)法進(jìn)行合并的,在內(nèi)核代碼中特別表明了如下注釋:

/* If we are here, it means order is >= pageblock_order.
* We want to prevent merge between freepages on isolate
* pageblock and normal pageblock. Without this, pageblock
* isolation could cause incorrect freepage or CMA accounting.
*
* We don't want to hit this code for the more frequent
* low-order merging.
*/

其對(duì)應(yīng)的代碼處理如下圖所示,其代碼主要目的有兩點(diǎn),其一是保證可以充分地進(jìn)行頁(yè)塊的合并,從而盡量減少內(nèi)存碎片化;其二是保證特殊用途的內(nèi)存塊不受影響。

最后根據(jù)實(shí)際情況,通過(guò)函數(shù)list_add(&page->lru, &zone->free_area[order].free_list[migratetype])或者函數(shù)list_add_tail(&page->lru,&zone->free_area[order].free_list[migratetype])把合并后的page添加到對(duì)應(yīng)的鏈表中。

總結(jié)

不同平臺(tái),不同內(nèi)核版本的系統(tǒng),在內(nèi)存處理上或許會(huì)存在或多或少的差異,但其核心思想是相同的。通過(guò)本文,我們可以詳細(xì)地了解Buddy中內(nèi)存申請(qǐng)和釋放的處理方式,以及當(dāng)內(nèi)存不足時(shí),Buddy是如何處理的。

作者介紹

趙青窕,51CTO社區(qū)編輯,從事多年驅(qū)動(dòng)開(kāi)發(fā)。研究興趣包含安全OS和網(wǎng)絡(luò)安全領(lǐng)域,發(fā)表過(guò)網(wǎng)絡(luò)相關(guān)專利。

責(zé)任編輯:華軒 來(lái)源: 51CTO
相關(guān)推薦

2024-01-01 18:59:15

KubernetesCPU內(nèi)存

2018-12-06 10:22:54

Linux內(nèi)核內(nèi)存

2022-07-19 13:31:18

Buddy算法內(nèi)存管理框架

2022-07-10 20:47:39

linux中虛擬內(nèi)存

2016-08-11 14:49:34

Java垃圾回收機(jī)制異常

2013-06-04 14:21:20

Vector內(nèi)存釋放

2024-05-06 11:19:20

內(nèi)存池計(jì)算機(jī)編程

2022-05-18 10:49:57

運(yùn)維數(shù)據(jù)

2020-10-23 06:56:00

C語(yǔ)言動(dòng)態(tài)字符串

2018-01-19 10:37:00

2021-05-17 09:28:59

鴻蒙HarmonyOS應(yīng)用

2009-06-10 22:03:40

JavaScript內(nèi)IE內(nèi)存泄漏

2021-05-21 09:25:11

鴻蒙HarmonyOS應(yīng)用

2011-08-16 15:13:49

IOS編程內(nèi)存

2012-09-13 15:37:21

linux內(nèi)存

2024-12-12 09:24:28

RocksDB服務(wù)器

2017-05-04 20:15:51

iOSNSTimer循環(huán)引用

2022-11-11 08:00:00

決策樹機(jī)器學(xué)習(xí)監(jiān)督學(xué)習(xí)

2024-02-05 21:07:51

C++內(nèi)存編程語(yǔ)言

2017-03-01 10:45:39

Linux驅(qū)動(dòng)技術(shù)內(nèi)存申請(qǐng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

久9久9色综合| 中文字幕视频在线免费欧美日韩综合在线看 | 在线观看免费高清视频97| 精品国产乱码久久久久久天美 | 欧美大片免费久久精品三p| 国产精品美女久久久久久| 国产成人综合精品三级| 美女精品一区| 伊人久久大香线蕉综合热线| 成人3d精品动漫精品一二三| 欧美日韩精品| 欧美xxav| 黄色在线网站噜噜噜| 国产系列第一页| 欧美xxxxxxxxx| 婷婷久久综合九色国产成人| 国产精品一区二区黑丝| 国产精品一区2区3区| 色哟哟在线观看| 久久久久久久久久伊人| 日韩精品高清在线| 精品国产乱码久久久久久老虎| 亚洲色图制服诱惑| 国产精品看片你懂得 | 国产伦理精品| 亚洲一区尤物| 5566成人精品视频免费| 日韩精品久久久久久久玫瑰园 | 免费看男男www网站入口在线| 韩国一区二区三区美女美女秀| 久久久成人的性感天堂| 日韩午夜在线影院| 日本高清无吗v一区| 午夜私人影院久久久久| 波多野结衣在线aⅴ中文字幕不卡| 成人性生交大片免费看视频在线| 午夜精品爽啪视频| 亚洲午夜久久久| 色先锋资源久久综合5566| 国产精品热视频| 91久久嫩草影院一区二区| 国产精品99久久99久久久二8| 国产啪精品视频网站| 久久久国产精品午夜一区ai换脸| 99在线观看免费视频精品观看| 国产成人精品亚洲线观看| 国产另类xxxxhd高清| av不卡高清| 美女av在线免费看| 亚洲成a人片| 成人av三级| 国精品产品一区| 日韩在线网址| 日韩成人免费看| 欧美视频在线看| 欧美精品免费看| 国产v亚洲v天堂无码| 福利在线小视频| 九色在线91| 欧美大片aaa| 成人免费网址| 欧美久久亚洲| 国产99久久久久久免费看农村| 宅男在线国产精品| 国产在线观看一区二区三区| 精品日韩美女| 日本1区2区| 99国产精品| 日韩欧美在线网址| 欧美丰满嫩嫩电影| 亚洲精品在线电影| 欧美探花视频资源| 有码中文亚洲精品| 日韩欧美亚洲区| missav|免费高清av在线看| 欧美日韩国产色综合一二三四| 亚洲五月六月丁香激情| 欧美怡红院视频一区二区三区| 国产综合中文字幕| 欧美91在线| 污片在线观看一区二区| 国产精品久久久久久久久| 免费免费啪视频在线观看| 国产欧美日韩一区二区三区四区| 婷婷丁香激情综合| 视频直播国产精品| 国产内射老熟女aaaa| 免费av在线电影| 久久人体视频| 亚洲欧美aⅴ...| 青青草99啪国产免费| 黄色漫画在线免费观看| 久久亚洲精精品中文字幕| 国产99久久久精品| 国产亚洲欧美日韩精品| 福利在线小视频| 欧洲精品一区二区三区| 好吊妞国产欧美日韩免费观看网站| 日韩精品导航| 国产亚洲欧美日韩日本| 亚洲999一在线观看www| 狠狠色噜噜狠狠色综合久| 国产欧美在线一区二区| 国内在线免费高清视频| 国产日韩综合| 国产一区二区日韩精品欧美精品| 欧美不卡在线播放| 好吊妞国产欧美日韩免费观看网站| 国产精品污www在线观看| 国产色视频一区| 日本高清中文字幕在线| 国产一本一道久久香蕉| 97在线观看视频国产| 德国一级在线视频| 欧美美女在线观看| 一区二区三区免费在线观看| 国产精品电影网| 伊人春色在线| 国产视频一区免费看| 欧美成人福利视频| 欧美日韩福利在线| 色香欲www7777综合网| 精品一区二区成人精品| 国产偷亚洲偷欧美偷精品| 黑人另类av| 精品国产丝袜高跟鞋| 秋霞电影网一区二区| 欧美一级高清免费播放| 久久另类ts人妖一区二区| 久久久久久77777| 欧美久色视频| 久久精品电影一区二区| 久色视频在线| 国产欧美日韩视频在线观看| 国产精品三区四区| 精品少妇3p| 亚洲欧美国内爽妇网| 在线观看黄色| 波多野结衣在线aⅴ中文字幕不卡| 国产精品一区久久久| 姬川优奈av一区二区在线电影| 一区二区三区中文字幕| 成人av网站观看| 中文字幕21页在线看| 久久美女高清视频| 国产高清不卡av| 成人天堂yy6080亚洲高清 | 国产一级二级三级在线观看| 极品av少妇一区二区| 嘿咻视频在线看| 国产伦精品一区二区三区视频孕妇 | 久久精品magnetxturnbtih| 欧美高清视频在线观看| 最近中文字幕mv2018在线高清| 一本一道久久综合狠狠老精东影业| 欧美激情视频一区| 欧美人与性动交α欧美精品济南到| 老司机精品久久| 国产精品日韩欧美| 欧美色网在线| 欧美日韩国产综合一区二区三区| 国产欧美在线一区| 香蕉久久夜色精品国产| 日韩美女中文字幕| 亚洲福利影视| 亚洲欧美激情视频| 激情影院在线观看| 一区av在线播放| 日日躁夜夜躁aaaabbbb| 懂色av一区二区三区蜜臀| 日本一区二区久久精品| 自拍欧美日韩| 99re在线观看| 日韩精品不卡一区二区| 高清视频欧美一级| www.久久久.com| 中文字幕9999| 欧美三级网站| 精品捆绑美女sm三区| 国产视频在线看| 午夜精品在线视频一区| 国产精品午夜久久久久久| 中文字幕第一区综合| 成人亚洲精品777777大片| 91麻豆免费看| 亚洲高清在线免费观看| 97久久超碰精品国产| 日本一本中文字幕| 99精品视频在线播放观看| 国产精品无码av在线播放| 91在线码无精品| 成熟了的熟妇毛茸茸| 久久影院午夜论| 国产第一页视频| 国产精品久久久久久久久免费樱桃 | 国产精品白丝久久av网站| 亚洲精品一区二区三区不| 亚洲涩涩在线| 欧美精品日韩www.p站| 亚洲电影一区|