日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

autojs遍历当前页面所有控件_伙伴系统:页面分配器

發布時間:2023/12/18 windows 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 autojs遍历当前页面所有控件_伙伴系统:页面分配器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

概述:

本篇主要是對伙伴系統的頁面分配器的實現進行一個梳理。在內核中伙伴系統算得上內存管理的一個基石了,畢竟頁面的分配全權由它負責,即使是slab分配器也是在它的基礎上進行實現的。頁面分配器的函數在內核中有著各種各樣的版本,不論是返回虛擬地址的還是返回struct page指針的,最終都會調用一個共同的接口:__alloc_pages_nodemask()

頁面分配API:

以下是幾個常見的頁面分配函數,可以看到最終都會調用__alloc_pages_nodemask()

__alloc_pages_node /*返回struct page的指針*/__alloc_pages__alloc_pages_nodemaskalloc_pages /*返回struct page的指針*/alloc_pages_current__alloc_pages_nodemask__get_free_pages /*返回頁面的虛擬地址*/__get_free_pagesalloc_pagesalloc_pages_current__alloc_pages_nodemask

核心梳理__alloc_pages_nodemask():

上面我們看到__alloc_pages_nodemask()即頁面分配器的'心臟'了,接下來我們就梳理下這顆'心臟'中都具體做了哪些事情,主要有三步:

__alloc_pages_nodemaskprepare alloc_context //1.準備參數get_page_from_freelist //2.快路徑嘗試分配內存 __alloc_pages_slowpath //3.慢路徑嘗試分配內存

細節如下:

由于分配過程很復雜,會涉及到大量的判斷,以及numa node和zone的選擇,所以會根據用戶傳參、進程配置(process flags)以及系統配置(mem policy或cgroup等)去整理一些參數,通過這些參數來控制后續內存分配和內存回收的行為。

1. 參數整理:

對__alloc_pages_nodemask()中的形參進行處理,整合出三個關鍵變量alloc_mask、alloc_flag以及struct alloc_context。(第一次整理后參數給fasthpath使用,若fastpath分配失敗,進入slowpath前還會微調這些參數)

alloc_mask:存放處理后的gfp_mask。處理主要包括:1.過濾無效的mask;2.根據是否開啟cpuset添加__GFP_HARDWALL;3.若請求發生在進程中,繼承任務的GFP_FS/IO的行為。alloc_flag:存放一些功能行為的mask。功能行為包括:1.cpuset是否開啟;2.watermark的水位線用哪根。3.請求發生在進程中,繼承任務的PF_MEMALLOC_xx的行為。alloc_context:存放了關于從哪獲取pageblock的參數。參數主要包括:zonelist、nodemask和preferred_zoneref

2. 快路徑(fastpath)分配:

get_page_from_freelist //從preferred zonelist中分pagezone_watermark_fast/ok //檢測水位,具體是min low high由ALLOC_WMARK_xx決定node_reclaim //wmark不ok,就根據回收模式判斷是否進行回收rmqueue //wmark很ok,分配pagermqueue_pcplist //order為0時,從pcp中分配__rmqueue_smallest //order大于0時,從free_area[]中分配

快路徑總結:
(整體進入for循環,遍歷嘗試zonelist中的zone直至分配內存成功或失敗,for循環中的處理如下)
1. 參數檢查,若有不滿足,直接continue跳過當前zone;
2. 檢查水位zone_watermark_fast/ok。其中high low min水位線用哪根兒具體由alloc_flags中的ALLOC_WMARK_xx標志決定;
3. 若水位不ok,則根據回收模式zone_reclaim_mode的設置,判斷是回收或是跳過當前zone,倘若最終沒一個zone是ok的,則快路徑失敗,進入慢路徑slowpath。
4. 若水位很ok,都符合了的話則rmqueue函數嘗試分配頁面,其中會區分order-0和非order-0的情況。

watermark的檢測:

首先wmark_pages()會根據alloc_flags中設置的是min或low或high去算出該zone的watermark是多少;然后將該watermark傳入zone_watermark_ok()判斷該zone的free pages是否滿足該水線。(檢查過程會根據內存分配的緊急程度放寬watermark)

(詳見章節: 內存回收(一):watermark與lowmem_reserve)。

核心函數rmqueue():

get_page_from_freelist()函數中做了一系列檢查,都是為了最終能調用rmqueue()函數從zone中拿到合適order的內存。細看上面的框圖,我們可以發現rmqeue()中根據order是否為0會分別調用rmqueue_pcplist()或__rmqueue_smallest(),原因如下:

  • order=0:

內核中將order-0的請求和大于order-0的請求在處理上做了區分。現在的處理器動不動就十幾個核,而zone就那么幾個,當多個核要同時訪問同一個zone的時候,不免要在zone的鎖的競爭上耗費大量時間。社區開發者發現系統中對order-0的請求在內核中出現的頻次極高,且order-0所占內存僅一個頁的大小,于是就實現了per cpu的"內存池",用來滿足order-0頁面的分配,這樣就在一定程度上緩解了伙伴系統在zone的鎖上面的競爭。

static struct page *rmqueue_pcplist(...) {/*關閉本地中斷并保存中斷狀態(因為中斷上下文也可以分配內存)*/local_irq_save(flags);/*獲取當前CPU上目標zone中的per_cpu_pages指針*/pcp = &this_cpu_ptr(zone->pageset)->pcp;/*獲取per_cpu_pages中制定遷移類型的頁面list*/list = &pcp->lists[migratetype];/*從鏈表上摘取目標頁面*/page = __rmqueue_pcplist(zone, migratetype, alloc_flags, pcp, list);/*若分配成功,更新當前zone的統計信息*/if (page) {__count_zid_vm_events(PGALLOC, page_zonenum(page), 1 << order);zone_statistics(preferred_zone, zone);}/*恢復中斷*/local_irq_restore(flags);return page; }
  • order>0:

在__rmqueue_smallest()中從小到大循環遍歷各個order的free_list鏈表,直到使用get_page_from_free_area()成功從鏈表上摘取到最小且合適(order和migratetype都合適)的pageblock

__rmqueue_smallest()get_page_from_free_area()

3. 慢路徑(slowpath)分配

__alloc_pages_slowpathwake_all_kswapds //首先喚醒所有kswapd線程,并確保slowpath過程中一直是醒著的get_page_from_freelist //調整一下alloc_flags,嘗試分配get_page_from_freelist //調整一下alloc_flags和zonelist,再試下分配__alloc_pages_direct_reclaim //reclaim后再嘗試分配,屬于同步回收__alloc_pages_direct_compact //compact后再嘗試分配,屬于同步回收__alloc_pages_may_oom //反復嘗試reclaim和compact后仍不成功,則oom殺進程后再嘗試分配,屬于同步回收

慢路徑總結:

快路徑(fastpath)檢查了各個zone的low watermark,若所有zone的內存水位線都低于low,則失敗并進入慢路徑(slowpath)。

1. 慢路徑第一件事就是先喚醒所有的kswapd內核線程展開異步回收。(異步回收)
2. 由于在進入慢路徑時會對alloc_flags進行調整,且已經開啟了異步回收,再次嘗試分配或許會成功。
3. 再次調整alloc_flags以及zonelist后嘗試分配或許會成功。
4. 調用__alloc_pages_direct_reclaim(),其中會先進行直接內存回收,然后嘗試分配內存。(同步回收)
5. 調用__alloc_pages_direct_compact(),其中會進行內存壓縮(或內存規整),掃描free_area[]對碎片化的內存進行整理,然后嘗試分配內存。(同步回收)
6. 調用__alloc_pages_may_oom()觸發OOM,殺掉得分最高的進程,然后嘗試分配內存。(同步回收)
7. 整個過程會根據實際情況可能循環嘗試3、4、5三個步驟,或循環嘗試3、4、5、6四個步驟。

4. slowpath中的各種回收機制

下面梳理了slowpath中四種回收機制的調用關系,細節待補充。

4.1 slowpath中的kswapd(異步回收)

創建kswapd: kernel啟動時會調用kswapd_init()為每個NUMA node都創建一個kswapd內核線程。

kswapd_initkswapd_runkthread_run(kswapd, ..)

喚醒kswapd: __alloc_pages_nodemask()分配過程中,當watermark低于low時會喚醒kswapd進行異步回收。

wake_all_kswapdswakeup_kswapd

4.2 slowpath中的reclaim(同步回收)

__alloc_pages_direct_reclaim__perform_reclaimtry_to_free_pagesdo_try_to_free_pagesshrink_zonesget_page_from_freelist

4.3 slowpath中的compact(同步回收)

__alloc_pages_direct_reclaim__perform_reclaimtry_to_free_pagesdo_try_to_free_pagesshrink_zonesget_page_from_freelist

4.4 slowpath中的OOM(同步回收)

__alloc_pages_may_oomout_of_memoryoom_kill_process

原創文章,轉載和引用請注明出處。

作者:Yann Xu

總結

以上是生活随笔為你收集整理的autojs遍历当前页面所有控件_伙伴系统:页面分配器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。