AndroidU 進(jìn)程基礎(chǔ)篇(1/2)

一 進(jìn)程介紹

安卓基于Linux內(nèi)核揽乱,設(shè)備開(kāi)機(jī)后,第一個(gè)安卓進(jìn)程為zygote進(jìn)程憋肖,隨后fork system_server(上層)萌衬,其他上層進(jìn)程需要通過(guò)fork system-server進(jìn)程來(lái)創(chuàng)建。因此進(jìn)程的創(chuàng)建毕源、調(diào)度浪漠、銷(xiāo)毀是進(jìn)程篇的核心內(nèi)容。

  • 進(jìn)程的創(chuàng)建[四大組件通過(guò)ams啟動(dòng)進(jìn)程]
  • 進(jìn)程的調(diào)度[前臺(tái)進(jìn)程霎褐、后臺(tái)進(jìn)程址愿、可見(jiàn)/不可見(jiàn)進(jìn)程、緩存進(jìn)程]
  • 當(dāng)進(jìn)程查殺[根據(jù)進(jìn)程當(dāng)前狀態(tài)來(lái)決定查殺內(nèi)容]

用戶打開(kāi)app/切換app冻璃,都希望能夠快速的完成這個(gè)操作必盖。應(yīng)用數(shù)據(jù)未被加載時(shí)拌牲,進(jìn)程不存在,需要冷啟動(dòng)歌粥。當(dāng)啟動(dòng)了大量的進(jìn)程后塌忽,系統(tǒng)內(nèi)存空間吃緊,那么如何查殺進(jìn)程又是一個(gè)問(wèn)題失驶。因此在進(jìn)程啟動(dòng)時(shí)需要根據(jù)啟動(dòng)意圖來(lái)更新lru進(jìn)程的重要性土居,在查殺時(shí)有策略的查殺。
這個(gè)進(jìn)程重要性的更新機(jī)制就是OomAdjuster


image.png

二 進(jìn)程調(diào)度介紹

oomadj官方文檔
https://android.googlesource.com/platform/frameworks/base/+/master/services/core/java/com/android/server/am/OomAdjuster.md
重點(diǎn)總結(jié):
The Android OS runs with limited hardware resources, i.e. CPU/RAM/Power. To strive for the better performance, Oom Ajuster is introduced to tweak the following 3 major factors:

  • Process State
    • Wildly used by the System Server, i.e., determine if it's foreground or not, change the GC behavior, etc.
    • Defined in ActivityManager#PROCESS_STATE_*
  • Oom Adj score
    • Used by the lmkd to determine which process should be expunged on memory pressure.
    • Defined in ProcessList#*_ADJ
  • Scheduler Group
    • Used to tweak the process group, thread priorities.
    • Top process is scheduled to be running on a dedicated big core, while foreground processes take the other big cores; background processes stay with LITTLE cores instead.

翻譯一下重點(diǎn)在于三個(gè)值的更新

  1. 更新進(jìn)程狀態(tài).
[computeOomAdjLSP]
state.setCurProcState(procState);
  1. 更新oom分?jǐn)?shù).
[computeOomAdjLSP]
state.setCurAdj(adj);
  1. 更新進(jìn)程所屬的進(jìn)程組.
              switch (curSchedGroup) {
                  case SCHED_GROUP_BACKGROUND:
                      processGroup = THREAD_GROUP_BACKGROUND;
                      break;
                  case SCHED_GROUP_TOP_APP:
                  case SCHED_GROUP_TOP_APP_BOUND:
                      processGroup = THREAD_GROUP_TOP_APP;
                      break;
                  case SCHED_GROUP_RESTRICTED:
                      processGroup = THREAD_GROUP_RESTRICTED;
                      break;
                  default:
                      processGroup = THREAD_GROUP_DEFAULT;
                      break;
              }

4.1 computeOomAdjLSP更新oomadj與procState

        // Do final modification to adj.  Everything we do between here and applying
        // the final setAdj must be done in this function, because we will also use
        // it when computing the final cached adj later.  Note that we don't need to
        // worry about this for max adj above, since max adj will always be used to
        // keep it out of the cached vaues.
        state.setCurAdj(adj);
        state.setCurCapability(capability);
        state.setCurrentSchedulingGroup(schedGroup);
        state.setCurProcState(procState);
        state.setCurRawProcState(procState);
        state.updateLastInvisibleTime(hasVisibleActivities);
        state.setHasForegroundActivities(foregroundActivities);
        state.setCompletedAdjSeq(mAdjSeq);
        state.setCurBoundByNonBgRestrictedApp(boundByNonBgRestricted);

        // if curAdj or curProcState improved, then this process was promoted
        return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState
                || state.getCurCapability() != prevCapability;

4.2 applyOomAdjLSP設(shè)置進(jìn)程所屬狀態(tài)組

computeOomAdjLSP更新完oomadj與procState后通過(guò)applyOomAdjLSP來(lái)更新凍結(jié)情況與設(shè)置進(jìn)程狀態(tài)組

    /** Applies the computed oomadj, procstate and sched group values and freezes them in set* */
    @GuardedBy({"mService", "mProcLock"})
    private boolean applyOomAdjLSP(ProcessRecord app, boolean doingAll, long now,
            long nowElapsed, @OomAdjReason int oomAdjReson) {
// 省略嬉探。擦耀。
                switch (curSchedGroup) {
                    case SCHED_GROUP_BACKGROUND:
                        processGroup = THREAD_GROUP_BACKGROUND;
                        break;
                    case SCHED_GROUP_TOP_APP:
                    case SCHED_GROUP_TOP_APP_BOUND:
                        processGroup = THREAD_GROUP_TOP_APP;
                        break;
                    case SCHED_GROUP_RESTRICTED:
                        processGroup = THREAD_GROUP_RESTRICTED;
                        break;
                    default:
                        processGroup = THREAD_GROUP_DEFAULT;
                        break;
                }
                mProcessGroupHandler.sendMessage(mProcessGroupHandler.obtainMessage(
                        0 /* unused */, app.getPid(), processGroup, app.processName));
---分割線
【OomAdjuster-mProcessGroupHandler】
        mProcessGroupHandler = new Handler(adjusterThread.getLooper(), msg -> {
            final int pid = msg.arg1;
            final int group = msg.arg2;
            if (pid == ActivityManagerService.MY_PID) {
                // Skip setting the process group for system_server, keep it as default.
                return true;
            }
            if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setProcessGroup "
                        + msg.obj + " to " + group);
            }
            try {
//調(diào)用native方法設(shè)置進(jìn)程組
                setProcessGroup(pid, group);
            } catch (Exception e) {
                if (DEBUG_ALL) {
                    Slog.w(TAG, "Failed setting process group of " + pid + " to " + group, e);
                }
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }
            return true;
        });
---分割線
【Process.java】
    /**
     * Sets the scheduling group for a process and all child threads
     * @hide
     * @param pid The identifier of the process to change.
     * @param group The target group for this process from THREAD_GROUP_*.
     *
     * @throws IllegalArgumentException Throws IllegalArgumentException if
     * <var>tid</var> does not exist.
     * @throws SecurityException Throws SecurityException if your process does
     * not have permission to modify the given thread, or to use the given
     * priority.
     *
     * group == THREAD_GROUP_DEFAULT means to move all non-background priority
     * threads to the foreground scheduling group, but to leave background
     * priority threads alone.  group == THREAD_GROUP_BACKGROUND moves all
     * threads, regardless of priority, to the background scheduling group.
     * group == THREAD_GROUP_FOREGROUND is not allowed.
     *
     * Always sets cpusets.
     */
    @UnsupportedAppUsage
    public static final native void setProcessGroup(int pid, int group)
            throws IllegalArgumentException, SecurityException;

每個(gè)進(jìn)程計(jì)算oom時(shí)機(jī),計(jì)算oom過(guò)程涩堤,計(jì)算oom結(jié)果保存眷蜓,計(jì)算結(jié)果應(yīng)用則是幾個(gè)重點(diǎn)的分析方向。
進(jìn)程重要性

2.1 Process State

[ActivityManager.java]

import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_RECENT;
import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT;
import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT_UI;
import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;

2.2 OOM_ADJ

import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_ACTIVITY;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_ALLOWLIST;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_BACKUP;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_BIND_SERVICE;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_COMPONENT_DISABLED;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_EXECUTING_SERVICE;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_FINISH_RECEIVER;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_GET_PROVIDER;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_NONE;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_PROCESS_BEGIN;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_PROCESS_END;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_REMOVE_PROVIDER;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_REMOVE_TASK;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_RESTRICTION_CHANGE;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_SHELL;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_SHORT_FGS_TIMEOUT;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_START_RECEIVER;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_START_SERVICE;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_STOP_SERVICE;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_SYSTEM_INIT;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_UID_IDLE;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_UI_VISIBILITY;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_UNBIND_SERVICE;

2.3 Scheduler Group

import static android.os.Process.SCHED_OTHER;
import static android.os.Process.THREAD_GROUP_BACKGROUND;
import static android.os.Process.THREAD_GROUP_DEFAULT;
import static android.os.Process.THREAD_GROUP_RESTRICTED;
import static android.os.Process.THREAD_GROUP_TOP_APP;
import static android.os.Process.THREAD_PRIORITY_DISPLAY;
import static android.os.Process.THREAD_PRIORITY_TOP_APP_BOOST;
import static android.os.Process.setProcessGroup;
import static android.os.Process.setThreadPriority;
import static android.os.Process.setThreadScheduler;
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末胎围,一起剝皮案震驚了整個(gè)濱河市吁系,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌白魂,老刑警劉巖汽纤,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異福荸,居然都是意外死亡蕴坪,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)敬锐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)背传,“玉大人,你說(shuō)我怎么就攤上這事台夺⌒遥” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵谒养,是天一觀的道長(zhǎng)挺狰。 經(jīng)常有香客問(wèn)我,道長(zhǎng)买窟,這世上最難降的妖魔是什么丰泊? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮始绍,結(jié)果婚禮上瞳购,老公的妹妹穿的比我還像新娘。我一直安慰自己亏推,他們只是感情好学赛,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布年堆。 她就那樣靜靜地躺著,像睡著了一般盏浇。 火紅的嫁衣襯著肌膚如雪变丧。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,246評(píng)論 1 308
  • 那天绢掰,我揣著相機(jī)與錄音痒蓬,去河邊找鬼。 笑死滴劲,一個(gè)胖子當(dāng)著我的面吹牛攻晒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播班挖,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼鲁捏,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了萧芙?” 一聲冷哼從身側(cè)響起给梅,我...
    開(kāi)封第一講書(shū)人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎末购,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體虎谢,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡盟榴,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了婴噩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡几莽,死狀恐怖迅办,靈堂內(nèi)的尸體忽然破棺而出章蚣,到底是詐尸還是另有隱情站欺,我是刑警寧澤,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布矾策,位于F島的核電站,受9級(jí)特大地震影響峭沦,放射性物質(zhì)發(fā)生泄漏贾虽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一吼鱼、第九天 我趴在偏房一處隱蔽的房頂上張望蓬豁。 院中可真熱鬧,春花似錦地粪、人聲如沸取募。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至付魔,卻和暖如春聊品,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背几苍。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工翻屈, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留妻坝,地道東北人伸眶。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像厘贼,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子圣拄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容