主頁 > 作業系統 > android功耗優化(2)--對齊喚醒

android功耗優化(2)--對齊喚醒

2020-09-10 00:34:03 作業系統

概況

Android手機上安裝的很多應用都會頻繁喚醒手機(喚醒系統、喚醒螢屏),造成手機耗電等現象,良好的對齊喚醒管理方案,就是對后臺應用待機時不頻繁喚醒,智能節省電量,

實作原理:APK作為該功能的入口,勾選應用后,將勾選的應用寫入黑名單,并通知framework黑名單內容變化;framework接收到通知后,自動獲取黑名單中的應用,保存到串列中;在framework呼叫介面中檢測應用是否在黑名單中,如果在黑名單中則檢測鬧鐘型別,如果鬧鐘型別是0或2,對應修改為1或3,

應用層功能實作

APK界面初始化

在ForbitAlarmLogic構造方法中初始化了陣列串列listPkgs、forbitPkgs、allowPkgs、showPkgs,

listPkgs:表示需要設定對齊喚醒的應用,如果這些應用已經安裝,就會顯示在對齊喚醒設定的界面上,初始資料從/data/data/com.***.android.security/app_bin/forbitapplist.xml中獲取,如果檔案不存在,則從本地資源陣列security_array_savepower_forbitalarms中獲取,

forbitPkgs:表示對齊喚醒名單,即禁止喚醒的名單,界面勾選的應用,初始資料從SharedPreference資料庫名ManagerUtil.PRE_NAME(com.***.android.savepowermanager_preferences)中獲取鍵值ManagerUtil.FORBIT_ALARM_APP_LIST_KEY中保存的資料,將獲取的資料保存到forbitPkgs陣列中,如果沒有資料則回傳null,

allowPkgs:表示允許喚醒的名單,界面沒有勾選的應用,初始資料從SharedPreference資料庫ManagerUtil.PRE_NAME(com.***.android.savepowermanager_preferences)中獲取鍵值為ManagerUtil.ALLOW_ALARM_APP_LIST_KEY中保存的資料,將獲取的資料保存到allowPkgs陣列串列中;如果沒有資料則回傳null,

showPkgs:表示要顯示在對齊喚醒設定界面的陣列應用串列,在資料初始化之前先將該陣列清空,對齊喚醒方案優化之前,該陣列保存的是listPkgs串列與已安裝應用的交集,優化之后,同時還保存了已安裝的第三方應用,

public ForbitAlarmLogic(Context ctx) {
    this.mCtx = ctx;
    pm = ctx.getPackageManager();
    xmlAppList = Util.getDefaultDataPath(ctx) + "/app_bin/applist.xml";
    String xmlFile = Util.getDefaultDataPath(ctx)+"/app_bin/forbitapplist.xml";
    File f = new File(xmlFile);
    if (!f.exists()) {
        Log.e("forbitapplist not exist!");
        String[] strs = mCtx.getResources().getStringArray(R.array.security_array_savepower_forbitalarms);
        for (String str : strs) {
            listPkgs.add(str);
        }
    } else {
        readFromXmlWithFilename(xmlFile, listPkgs);
    }
//      readFromXml();
    Set<String> forbitset = (Set<String>)ManagerUtil.getPreferenceValue(mCtx, ManagerUtil.PRE_NAME,
            ManagerUtil.FORBIT_ALARM_APP_LIST_KEY, null, 4);
    if (forbitset != null) {
        Iterator<String> forbitir = forbitset.iterator();
        while(forbitir.hasNext()) {
            String forbit = forbitir.next();
            forbitPkgs.add(forbit);
        }
    }

    Set<String> allowset = (Set<String>)ManagerUtil.getPreferenceValue(mCtx, ManagerUtil.PRE_NAME,
            ManagerUtil.ALLOW_ALARM_APP_LIST_KEY, null, 4);
    if (allowset != null) {
        Iterator<String> allowir = allowset.iterator();
        while(allowir.hasNext()) {
            String allow = allowir.next();
            allowPkgs.add(allow);
        }
    }
}
    public ArrayList<DroidApp> getListApps() {
        if (forbitPkgs.size() == 0) {
            Set<String> forbitset= (Set<String>)ManagerUtil.getPreferenceValue(mCtx, ManagerUtil.PRE_NAME,
                    ManagerUtil.FORBIT_ALARM_APP_LIST_KEY, null, 4);
            if (forbitset == null) {
                readFromXml();
                HashSet<String> forbitPkgsSet = new HashSet<String>();
                for (String pkg : forbitPkgs) {
                    forbitPkgsSet.add(pkg);
                }
                ManagerUtil.savePreferenceValue(mCtx, ManagerUtil.PRE_NAME,
                    ManagerUtil.FORBIT_ALARM_APP_LIST_KEY, forbitPkgsSet, 4);
            } else {
                Iterator<String> forbitir = forbitset.iterator();
                while(forbitir.hasNext()) {
                    String forbit = forbitir.next();
                    forbitPkgs.add(forbit);
                }
            }
        }
        showPkgs.clear();
        ArrayList<DroidApp> apps = new ArrayList<DroidApp>();
        
        final List<PackageInfo> installed = pm.getInstalledPackages(0);
       
        String name = null;
        for (final PackageInfo appInfo : installed){
            String pkg = appInfo.packageName;
            if (listPkgs.contains(pkg)) {
                DroidApp app = new DroidApp();
                name = pm.getApplicationLabel(appInfo.applicationInfo).toString();
                app.name = name;
                app.icon = appInfo.applicationInfo.loadIcon(pm);
                if (forbitPkgs.contains(pkg)) {
                    app.online_switch = true;
                } else if (allowPkgs.contains(pkg)) {
                    app.online_switch = false;
                } else {
                    app.online_switch = true;
                }
                app.pkg = pkg;
                apps.add(app);
                showPkgs.add(pkg);
                Log.d("in white list and installed package is : "+pkg);
            } else {
//              已經安裝的第三方應用
                if ((appInfo.applicationInfo.uid > 10000)
                        && (appInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0
                        && (appInfo.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0) {
                    String pkgName = appInfo.packageName;
                    DroidApp app = new DroidApp();
                    app.name = pm.getApplicationLabel(appInfo.applicationInfo).toString();
                    app.icon = appInfo.applicationInfo.loadIcon(pm);
//                    app.online_switch = true;
                    if (forbitPkgs.contains(pkg)) {
                        app.online_switch = true;
                    } else if (allowPkgs.contains(pkg)) {
                        app.online_switch = false;
                    } else {
                        app.online_switch = true;
                    }
                    app.pkg = pkgName;
                    apps.add(app);
                    showPkgs.add(pkgName);
                    Log.d("not in white list and installed third package is : "+pkgName);
                }
            }
        }
        return apps;
    }
private class GetListDataThread implements Runnable {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        appList = mFbAmLogic.getListApps();
        resultList.clear();

        for (DroidApp app : appList) {
            Log.d("getListApps appname = " + app.pkg);
            if (app.online_switch) {
                if (app.pkg != null && app.pkg.length() > 0) {
                    resultList.add(app.pkg);
                    saveList.add(app.pkg);
                }
            }
        }
        Message msg = Message.obtain();
        msg.what = MSG_SHOWLIST;
        handler.sendMessage(msg);
    }

}

ForbitAlarmLogic類的getListApps()方法中重新為forbitPkgs陣列賦值

如果forbitPkgs為空,即在構造方法中沒有獲取到資料,重新從上面資料庫中獲取資料;如果仍然是空,則從/data/data/com.***.android.security/app_bin/applist.xml檔案中獲取,保存到forbitPkgs陣列中,

手機管家中顯示的對齊喚醒名單主要有:
(1)、forbitapplist.xml檔案與已安裝應用的交集應用;

(2)、已安裝的第三方應用,

APK回應機制

APK在啟動之后,就已經設定好了黑白名單,初始化程序就是加載界面的程序,

回應點擊事件

界面初始化完畢之后,將處于勾選狀態的應用保存到兩個陣列串列:resultList、saveList,回應點擊事件時,將應用移除resultList串列,或添加到resultList串列中,

界面退出機制

在onPause()方法中判斷resultList與saveList是否相同,如果不相同則重新保存對齊喚醒名單,并通知AlarmManagerService,

    public void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        new Thread(new Runnable() {
 
            @Override
            public void run() {
                // TODO Auto-generated method stub
                boolean isSameContent = true;
                for (int i = 0; i < saveList.size(); i++) {
                    Log.d("saveList "+ i + " = "+saveList.get(i));
                }
                for (int j = 0; j < resultList.size(); j++) {
                    Log.d("resultList "+ j + " = "+resultList.get(j));
                }
 
                if (saveList.size() == resultList.size()) {
                    Log.i("saveList == resultList");
                    for (String result : resultList) {
                        String xmlAppList = "/data/data/com.***.android.security/app_bin/applist.xml";
                        ArrayList<String> forbitPkgs = new ArrayList<String>();
                        ForbitAlarmLogic.readFromXmlWithFilename(xmlAppList, forbitPkgs);
                        if (!forbitPkgs.contains(result)) {
                            Log.i(result + "Not In applist.xml");
                            isSameContent = false;
                            break;
                        }
 
                        if (!saveList.contains(result)) {
                            Log.i(result + "Not In SaveList");
                            isSameContent = false;
                            break;
                        }
                    }
                } else {
                    Log.i("saveList Changed");
                    isSameContent = false;
                }
 
                if (!isSameContent) {
                    Log.i("ForbitAlarmSetting save Data");
                    mFbAmLogic.saveAlarmAppMap(resultList);
                }
            }
        }).start();
    }

(1)、如何重新保存名單?

首先,清空allowPkgs和forbitPkgs,即先清空允許啟動的應用串列和禁止啟動的應用串列,

其次,將禁止喚醒的應用(即界面上處于勾選狀態的應用)添加到forbitPkgs中,并寫入/data/data/com.***.android.security/app_bin/applist.xml檔案中,同時寫入對應鍵值為ManagerUtil.FORBIT_ALARM_APP_LIST_KEY資料庫中,

再次,將允許喚醒的應用(界面上沒有勾選的應用)添加到allowPkgs中,并寫入對應鍵值為ManagerUtil.ALLOW_ALARM_APP_LIST_KEY資料庫中,

最后,通知AlarmManagerService,

(2)、如何通知AlarmManagerService?

上面資料保存完畢后,發送廣播:com.***.android.savepower.forbitalarmapplistchanged,通知AlarmManagerService,

public static void notifyFramework(final Context ctx) {
    new Thread(){
        public void run() {
            try {
                Thread.sleep(200);
                Intent intent = new Intent();
                intent.setAction(ManagerUtil.INTENT_FORBITALARM_LIST_CHANGED);
                ctx.sendBroadcast(intent);
            } catch (InterruptedException e) {
                Log.e("applist.xml send broadcast error");
            }
        };
    }.start();
}

流程圖如下:

安裝第三方應用

在PackageReceiver類中接收到包安裝的廣播后,將第三方應用添加到白名單,重新獲取對齊喚醒資料,

              new Thread(new Runnable() {
                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        Log.d("automatically add newly installed applications into blacklist."
                                + " packageName = " + packageName);
 
                        synchronized (PackageReceiver.this) {
                            mForbitAlarmLogic = ForbitAlarmLogic
                                    .getInstance(mCtx);
                            mForbitAlarmLogic
                                    .packageReceiverApkAdded(packageName);
                        }
                    }
                }).start();

AlarmManagerService實作機制

接收廣播

當對齊喚醒名單發生變化時,會發送forbitalarmapplistchanged 廣播,AlarmManagerService定義了該廣播的接收器,用來接收APK發送的廣播,從applist.xml(/data/data/com.***.android.security/app_bin/applist.xml)檔案中讀取應用保存到全域變數mHashtable中,

class UpdateXmlReceiver extends BroadcastReceiver {

    public UpdateXmlReceiver() {
         IntentFilter filter = new IntentFilter();
         filter.addAction(ACTION_SAVEPOWER_UPDATEXML);
         getContext().registerReceiver(this, filter);
    }
    @Override
    public void onReceive(Context context, Intent intent) {
        synchronized (mLock) {
            // TODO Auto-generated method stub
            if(YulongFeature.FEATURE_REDUCE_RTC_WAKEUP){
                mHashtable.clear();
                Slog.d(TAG, "Receive savepower broadcast, read xml again.");
                getPackageNameFromXml();
            }
        }
    }
}
private void getPackageNameFromXml() {
    FileReader permReader = null;

    try {
        permReader = new FileReader(xmlNewFile);
        Slog.d(TAG, "getPackageNameFromXml : read xmlNewFile ");
    } catch (FileNotFoundException e) {
        try {
            permReader = new FileReader(xmlFile);
            Slog.d(TAG, "getPackageNameFromXml : read xmlFile ");
        } catch (FileNotFoundException e1) {
            // TODO Auto-generated catch block
            Slog.d(TAG, "getPackageNameFromXml, can not find config xml ");
            return;
        }
    }

    try {
        XmlPullParser parser = Xml.newPullParser();
        parser.setInput(permReader);

        XmlUtils.beginDocument(parser, "channel");

        while (true) {
            XmlUtils.nextElement(parser);
            if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
                break;
            }

            String name = parser.getName();
            if ("item".equals(name)) {
                int id = Integer.parseInt(parser.getAttributeValue(null, "id"));
                if (id <= 0) {
                     Slog.w(TAG, "<item> without name at "
                             + parser.getPositionDescription());
                     XmlUtils.skipCurrentTag(parser);
                     continue;
                 }
                String packagename = parser.getAttributeValue(null, "name");
                if (packagename == null) {
                    Slog.w(TAG, "<item> without name at "
                            + parser.getPositionDescription());
                    XmlUtils.skipCurrentTag(parser);
                    continue;
                }
                Slog.d(TAG, "getPackageNameFromXml : id is " + id + "  name is " + packagename);

                mHashtable.put(id, packagename);

                XmlUtils.skipCurrentTag(parser);
            } else {
                XmlUtils.skipCurrentTag(parser);
                continue;
            }
        }
        permReader.close();
    } catch (XmlPullParserException e) {
        Slog.w(TAG, "Got execption parsing permissions.", e);
    } catch (IOException e) {
        Slog.w(TAG, "Got execption parsing permissions.", e);
    }
}

修改鬧鐘型別

在呼叫setImpl方法設定鬧鐘時,我們通過修改鬧鐘的型別來實作對齊喚醒功能,

if (type == AlarmManager.RTC_WAKEUP || type == AlarmManager.ELAPSED_REALTIME_WAKEUP) {
             if(mHashtable.containsValue(callingPackage)){
                if (AlarmManager.RTC_WAKEUP == type) {
                    type = AlarmManager.RTC;
                    Slog.v(TAG, "change alarm type RTC_WAKEUP to RTC for " + callingPackage);
                }
                if (AlarmManager.ELAPSED_REALTIME_WAKEUP == type) {
                    type = AlarmManager.ELAPSED_REALTIME;
                    Slog.v(TAG, "change alarm type ELAPSED_REALTIME_WAKEUP to ELAPSED_REALTIME for " + callingPackage);
                }
            }
        }

對齊喚醒添加機制

(1)、第三方應用全部添加到對齊喚醒名單;

(2)、禁止系統應用驗證前添加到對齊喚醒名單,避免導致系統例外,

A. 系統核心應用不允許加入對齊喚醒名單,即位于system/priv-app目錄下的應用不可以加入對齊喚醒名單;

轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/209.html

標籤:嵌入式

上一篇:痞子衡嵌入式:導致串行NOR Flash在i.MXRT下無法正常下載/啟動的常見因素之QE bit

下一篇:Android 功耗(3)---高通功耗問題分析方法

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • CA和證書

    1、在 CentOS7 中使用 gpg 創建 RSA 非對稱密鑰對 gpg --gen-key #Centos上生成公鑰/密鑰對(存放在家目錄.gnupg/) 2、將 CentOS7 匯出的公鑰,拷貝到 CentOS8 中,在 CentOS8 中使用 CentOS7 的公鑰加密一個檔案 gpg -a ......

    uj5u.com 2020-09-10 00:09:53 more
  • Kubernetes K8S之資源控制器Job和CronJob詳解

    Kubernetes的資源控制器Job和CronJob詳解與示例 ......

    uj5u.com 2020-09-10 00:10:45 more
  • VMware下安裝CentOS

    VMware下安裝CentOS 一、軟硬體準備 1 Centos鏡像準備 1.1 CentOS鏡像下載地址 下載地址 1.2 CentOS鏡像下載程序 點擊下載地址進入如下圖的網站,選擇需要下載的版本,這里選擇的是Centos8,點擊如圖所示。 決定選擇Centos8后,選擇想要的鏡像源進行下載,此 ......

    uj5u.com 2020-09-10 00:12:10 more
  • 如何使用Grep命令查找多個字串

    如何使用Grep 命令查找多個字串 大家好,我是良許! 今天向大家介紹一個非常有用的技巧,那就是使用 grep 命令查找多個字串。 簡單介紹一下,grep 命令可以理解為是一個功能強大的命令列工具,可以用它在一個或多個輸入檔案中搜索與正則運算式相匹配的文本,然后再將每個匹配的文本用標準輸出的格式 ......

    uj5u.com 2020-09-10 00:12:28 more
  • git配置http代理

    git配置http代理 經常遇到克隆 github 慢的問題,這里記錄一下幾種配置 git 代理的方法,解決 clone github 過慢。 目錄 git配置代理 git單獨配置github代理 git配置全域代理 配置終端環境變數 git配置代理 主要使用 git config 命令 git單獨 ......

    uj5u.com 2020-09-10 00:12:33 more
  • Linux npm install 裝包時提示Error EACCES permission denied解

    npm install 裝包時提示Error EACCES permission denied解決辦法 ......

    uj5u.com 2020-09-10 00:12:53 more
  • Centos 7下安裝nginx,使用yum install nginx,提示沒有可用的軟體包

    Centos 7下安裝nginx,使用yum install nginx,提示沒有可用的軟體包。 18 (flaskApi) [root@67 flaskDemo]# yum -y install nginx 19 已加載插件:fastestmirror, langpacks 20 Loading ......

    uj5u.com 2020-09-10 00:13:13 more
  • Linux查看服務器暴力破解ssh IP

    在公網的服務器上經常遇到別人爆破你服務器的22埠,用來挖礦或者干其他嘿嘿嘿的事情~ 這種情況下正確的做法是: 修改默認ssh的22埠 使用設定密鑰登錄或者白名單ip登錄 建議服務器密碼為復雜密碼 創建普通用戶登錄服務器(root權限過大) 建立堡壘機,實作統一管理服務器 統計爆破IP [root ......

    uj5u.com 2020-09-10 00:13:17 more
  • CentOS 7系統常見快捷鍵操作方式

    Linux系統中一些常見的快捷方式,可有效提高操作效率,在某些時刻也能避免操作失誤帶來的問題。 ......

    uj5u.com 2020-09-10 00:13:31 more
  • CentOS 7作業系統目錄結構介紹

    作業系統存在著大量的資料檔案資訊,相應檔案資訊會存在于系統相應目錄中,為了更好的管理資料資訊,會將系統進行一些目錄規劃,不同目錄存放不同的資源。 ......

    uj5u.com 2020-09-10 00:13:35 more
最新发布
  • vim的常用命令

    Vim的6種基本模式 1. 普通模式在普通模式中,用的編輯器命令,比如移動游標,洗掉文本等等。這也是Vim啟動后的默認模式。這正好和許多新用戶期待的操作方式相反(大多數編輯器默認模式為插入模式)。 2. 插入模式在這個模式中,大多數按鍵都會向文本緩沖中插入文本。大多數新用戶希望文本編輯器編輯程序中一 ......

    uj5u.com 2023-04-20 08:43:21 more
  • vim的常用命令

    Vim的6種基本模式 1. 普通模式在普通模式中,用的編輯器命令,比如移動游標,洗掉文本等等。這也是Vim啟動后的默認模式。這正好和許多新用戶期待的操作方式相反(大多數編輯器默認模式為插入模式)。 2. 插入模式在這個模式中,大多數按鍵都會向文本緩沖中插入文本。大多數新用戶希望文本編輯器編輯程序中一 ......

    uj5u.com 2023-04-20 08:42:36 more
  • docker學習

    ###Docker概述 真實專案部署環境可能非常復雜,傳統發布專案一個只需要一個jar包,運行環境需要單獨部署。而通過Docker可將jar包和相關環境(如jdk,redis,Hadoop...)等打包到docker鏡像里,將鏡像發布到Docker倉庫,部署時下載發布的鏡像,直接運行發布的鏡像即可。 ......

    uj5u.com 2023-04-19 09:26:53 more
  • 設定Windows主機的瀏覽器為wls2的默認瀏覽器

    這里以Chrome為例。 1. 準備作業 wsl是可以使用Windows主機上安裝的exe程式,出于安全考慮,默認情況下改功能是無法使用。要使用的話,終端需要以管理員權限啟動。 我這里以Windows Terminal為例,介紹如何默認使用管理員權限打開終端,具體操作如下圖所示: 2. 操作 wsl ......

    uj5u.com 2023-04-19 09:25:49 more
  • docker學習

    ###Docker概述 真實專案部署環境可能非常復雜,傳統發布專案一個只需要一個jar包,運行環境需要單獨部署。而通過Docker可將jar包和相關環境(如jdk,redis,Hadoop...)等打包到docker鏡像里,將鏡像發布到Docker倉庫,部署時下載發布的鏡像,直接運行發布的鏡像即可。 ......

    uj5u.com 2023-04-19 09:19:04 more
  • Linux學習筆記

    IP地址和主機名 IP地址 ifconfig可以用來查詢本機的IP地址,如果不能使用,可以通過install net-tools安裝。 Centos系統下ens33表示主網卡;inet后表示IP地址;lo表示本地回環網卡; 127.0.0.1表示代指本機;0.0.0.0可以用于代指本機,同時在放行設 ......

    uj5u.com 2023-04-18 06:52:01 more
  • 解決linux系統的kdump服務無法啟動的問題

    問題:專案麒麟系統服務器的kdump服務無法啟動,沒有相關日志無法定位問題。 1、查看服務狀態是關閉的,重啟系統也無法啟動 systemctl status kdump 2、修改grub引數,修改“crashkernel”為“512M(有的機器數值太大太小都會導致報錯,建議從128M開始試,或者加個 ......

    uj5u.com 2023-04-12 09:59:50 more
  • 解決linux系統的kdump服務無法啟動的問題

    問題:專案麒麟系統服務器的kdump服務無法啟動,沒有相關日志無法定位問題。 1、查看服務狀態是關閉的,重啟系統也無法啟動 systemctl status kdump 2、修改grub引數,修改“crashkernel”為“512M(有的機器數值太大太小都會導致報錯,建議從128M開始試,或者加個 ......

    uj5u.com 2023-04-12 09:59:01 more
  • 你是不是暴露了?

    作者:袁首京 原創文章,轉載時請保留此宣告,并給出原文連接。 如果您是計算機相關從業人員,那么應該經歷不止一次網路安全專項檢查了,你肯定是收到過資訊系統技術檢測報告,要求你加強風險監測,確保你提供的系統服務堅實可靠了。 沒檢測到問題還好,檢測到問題的話,有些處理起來還是挺麻煩的,尤其是線上正在運行的 ......

    uj5u.com 2023-04-05 16:52:56 more
  • 細節拉滿,80 張圖帶你一步一步推演 slab 記憶體池的設計與實作

    1. 前文回顧 在之前的幾篇記憶體管理系列文章中,筆者帶大家從宏觀角度完整地梳理了一遍 Linux 記憶體分配的整個鏈路,本文的主題依然是記憶體分配,這一次我們會從微觀的角度來探秘一下 Linux 內核中用于零散小記憶體塊分配的記憶體池 —— slab 分配器。 在本小節中,筆者還是按照以往的風格先帶大家簡單 ......

    uj5u.com 2023-04-05 16:44:11 more