亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android dumpsys簡介

 更新時間:2025年03月11日 09:55:36   作者:林奮斗同學(xué)  
本文詳細(xì)介紹了Android系統(tǒng)中的dumpsys工具,包括其原理、使用方法、環(huán)境要求和相關(guān)概念,dumpsys是一個強大的系統(tǒng)診斷工具,可以幫助開發(fā)者了解系統(tǒng)服務(wù)狀態(tài),分析問題,并設(shè)計新功能,感興趣的朋友一起看看吧

一、需求

  • 了解dumpsys原理,助于我們進一步了解Android系統(tǒng)的設(shè)計
  • 幫助我們分析問題,定位系統(tǒng)狀態(tài)
  • 設(shè)計新功能的需要

二、環(huán)境

  • 版本:Android 12
  • 平臺:SL8541E SPRD

三、相關(guān)概念

3.1 dumpsys

dumpsys 是一種在 Android 設(shè)備上運行的工具,可提供有關(guān)系統(tǒng)服務(wù)的信息??梢允褂?Android 調(diào)試橋 (adb) 從命令行調(diào)用 dumpsys,獲取在連接的設(shè)備上運行的所有系統(tǒng)服務(wù)的診斷輸出。

3.2 Binder

Binder是Android提供的一套進程間相互通信框架。用來實現(xiàn)多進程間發(fā)送消息,同步和共享內(nèi)存。

請?zhí)砑訄D片描述

3.3 管道

管道是一種IPC通信方式,分為有名管道和無名管道,無論是有名管道還是無名管道其原理都是在內(nèi)核開辟一塊緩存空間,這段緩存空間的操作是通過文件讀寫方式進行的。
有名管道與無名管道:
有名管道: 有名管道的通信可以通過管道名進行通信,進程間不需要有關(guān)系。
無名管道: 無名管道就是匿名管道,匿名管道通信的進程必須是父子進程。
管道為分半雙工和全雙工:
半雙工: 半雙工管道是單向通信,進程1只能向管道寫數(shù)據(jù),進程2只能從管道讀取數(shù)據(jù)。只有一個代表讀或者寫的FD(文件描述符)。
全雙工: 全雙工管道是雙向通信,有兩個文件描述符,代表讀和寫。

請?zhí)砑訄D片描述

四、dumpsys指令的使用

4.1 dumpsys使用

如下為執(zhí)行"adb shell dumpsys"指令,控制臺打印的內(nèi)容,其使用如下:

dumpsys執(zhí)行

4.2 dumpsys指令語法

(1)使用 dumpsys 的一般語法如下:

adb shell dumpsys [-t timeout] [--help | -l | --skip services | service [arguments] | -c | -h]

(2)如需獲取所連接設(shè)備的所有系統(tǒng)服務(wù)的診斷輸出,請運行 adb shell dumpsys。不過,這樣輸出的信息比您通常想要的信息多得多。若要使輸出更加可控,您可以通過在命令中添加相應(yīng)服務(wù)來指定要檢查的服務(wù)。例如,下面的命令會提供輸入組件(如觸摸屏或內(nèi)置鍵盤)的系統(tǒng)數(shù)據(jù):

adb shell dumpsys input

(3)如需查看可與 dumpsys 配合使用的系統(tǒng)服務(wù)的完整列表,請使用以下命令:

adb shell dumpsys -l

(4)命令行選項如下:

選項說明
-t timeout指定超時期限(秒)。如果未指定,默認(rèn)值為 10 秒。
–help輸出 dumpsys 工具的幫助文本。
-l輸出可與 dumpsys 配合使用的系統(tǒng)服務(wù)的完整列表。
–skip services指定您不希望包含在輸出中的 services。
service [arguments]指定您希望輸出的 service。某些服務(wù)可能允許您傳遞可選 arguments。如需了解這些可選參數(shù),請將 -h 選項與服務(wù)一起傳遞:
adb shell dumpsys procstats -h
-c指定某些服務(wù)時,附加此選項能以計算機可讀的格式輸出數(shù)據(jù)。
-h對于某些服務(wù),附加此選項可查看該服務(wù)的幫助文本和其他選項。

五、詳細(xì)設(shè)計

5.1 dumpsys流程圖

請?zhí)砑訄D片描述

5.2 dumpsys查看電池信息

5.2.1 dumpsys battery指令

請?zhí)砑訄D片描述

5.2.2 service->dump打印函數(shù)

@frameworks\base\services\core\java\com\android\server\BatteryService.java
private final class BinderService extends Binder {
    @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
            if (args.length > 0 && "--proto".equals(args[0])) {
                dumpProto(fd);
            } else {
                dumpInternal(fd, pw, args);
            }
        }
    ...
}
private void dumpInternal(FileDescriptor fd, PrintWriter pw, String[] args) {
    synchronized (mLock) {
        if (args == null || args.length == 0 || "-a".equals(args[0])) {
            pw.println("Current Battery Service state:");
            if (mUpdatesStopped) {
                pw.println("  (UPDATES STOPPED -- use 'reset' to restart)");
            }
            pw.println("  AC powered: " + mHealthInfo.chargerAcOnline);
            pw.println("  USB powered: " + mHealthInfo.chargerUsbOnline);
            pw.println("  Wireless powered: " + mHealthInfo.chargerWirelessOnline);
            pw.println("  Max charging current: " + mHealthInfo.maxChargingCurrent);
            pw.println("  Max charging voltage: " + mHealthInfo.maxChargingVoltage);
            pw.println("  Charge counter: " + mHealthInfo.batteryChargeCounter);
            pw.println("  status: " + mHealthInfo.batteryStatus);
            pw.println("  health: " + mHealthInfo.batteryHealth);
            pw.println("  present: " + mHealthInfo.batteryPresent);
            pw.println("  level: " + mHealthInfo.batteryLevel);
            pw.println("  scale: " + BATTERY_SCALE);
            pw.println("  voltage: " + mHealthInfo.batteryVoltage);
            pw.println("  temperature: " + mHealthInfo.batteryTemperature);
            pw.println("  technology: " + mHealthInfo.batteryTechnology);
        } else {
            Shell shell = new Shell();
            shell.exec(mBinderService, null, fd, null, args, null, new ResultReceiver(null));
        }
    }
}

5.3 dumpsys源碼分析

5.3.1 dumpsys服務(wù)編譯

dumpsys是個二進制可執(zhí)行程序,其通過bp進行編譯,并最終打包到system分區(qū)(system/bin/dumpsys)。

@frameworks\native\cmds\dumpsys\android.bp
cc_binary {
    name: "dumpsys",
    defaults: ["dumpsys_defaults"],
    srcs: [
        "main.cpp",
    ],
}

5.3.2 dumpsys入口函數(shù)

我們通過執(zhí)行adb指令 “adb shell dumpsys”,可以啟動dumpsys服務(wù),其對應(yīng)的入口函數(shù)如下:

@frameworks\native\cmds\dumpsys\main.cpp
int main(int argc, char* const argv[]) {
    signal(SIGPIPE, SIG_IGN);
    sp<IServiceManager> sm = defaultServiceManager();//獲取SM對象
    fflush(stdout);
    if (sm == nullptr) {
        ALOGE("Unable to get default service manager!");
        std::cerr << "dumpsys: Unable to get default service manager!" << std::endl;
        return 20;
    }
    Dumpsys dumpsys(sm.get());
    return dumpsys.main(argc, argv);//進入dumpsys服務(wù)
}

這邊比較關(guān)鍵的點是獲取ServiceManager對象。
大家通過打印可以發(fā)現(xiàn),dumpsys指令打印的數(shù)據(jù)是java進程的dump函數(shù),而dumpsys也是獨立的一個進程,那么dumpsys進程又是怎么和多個java進程通信的呢?沒錯,就是通過ServiceManager對象。
那么,ServiceManager對象是什么呢?ServiceManager是Binder IPC通信的管家,本身也是一個Binder服務(wù),他相當(dāng)于 “DNS服務(wù)器”,內(nèi)部存儲了serviceName與其Binder Service的對應(yīng)關(guān)系,管理Java層和native層的service,支持addService()、getService()、checkService、listServices()等功能。(Binder機制此處就不展開細(xì)說)

5.3.3 dumpsys服務(wù)打印

5.3.3.1 dumpsys解析參數(shù)

當(dāng)我們使用dumpsys指令,打印的數(shù)據(jù)太過冗長,一般會配合相關(guān)參數(shù)進行使用,例如:“dumpsys -l”、“dumpsys -t 100 battery”、“dumpsys --help”,第一步我們會先解析目標(biāo)參數(shù)。

@frameworks\native\cmds\dumpsys\dumpsys.cpp
int Dumpsys::main(int argc, char* const argv[]) {
    ...
    while (1) {
        ...
        c = getopt_long(argc, argv, "+t:T:l", longOptions, &optionIndex);//獲取指令參數(shù)
        ...
        switch (c) {
        case 0://長參數(shù)
            if (!strcmp(longOptions[optionIndex].name, "skip")) {//跳過某些服務(wù)打印
                skipServices = true;
            } else if (!strcmp(longOptions[optionIndex].name, "proto")) {
                asProto = true;
            } else if (!strcmp(longOptions[optionIndex].name, "help")) {//指令幫助
                usage();
                return 0;
            } else if (!strcmp(longOptions[optionIndex].name, "priority")) {
                ...
            } else if (!strcmp(longOptions[optionIndex].name, "pid")) {//只顯示服務(wù)的pid
                type = Type::PID;
            } else if (!strcmp(longOptions[optionIndex].name, "thread")) {//僅顯示進程使用情況
                type = Type::THREAD;
            }
            break;
        case 't'://超時時間設(shè)置,默認(rèn)10秒
            ...
            break;
        case 'T'://超時時間設(shè)置,默認(rèn)10秒
            ...
            break;
        case 'l'://顯示支持的服務(wù)列表
            showListOnly = true;
            break;
        default://其他參數(shù)
            fprintf(stderr, "\n");
            usage();
            return -1;
        }
    }
    ...
}

5.3.3.2 skippedServices列表構(gòu)造

dumpsys內(nèi)部構(gòu)造了skippedServices集合,用于記錄需要忽略的服務(wù)。

@frameworks\native\cmds\dumpsys\dumpsys.cpp
int Dumpsys::main(int argc, char* const argv[]) {
    ...
    for (int i = optind; i < argc; i++) {
    if (skipServices) {
        skippedServices.add(String16(argv[i]));//配置待忽略的服務(wù)
    } else {
        ...
    }
    ...
}

5.3.3.3 獲取支持服務(wù)列表

dumpsys通過ServiceManager獲取支持的服務(wù)集合,并排序。

@frameworks\native\cmds\dumpsys\dumpsys.cpp
int Dumpsys::main(int argc, char* const argv[]) {
    ...
    if (services.empty() || showListOnly) {
        services = listServices(priorityFlags, asProto);
        setServiceArgs(args, asProto, priorityFlags);
    }
    ...
}
Vector<String16> Dumpsys::listServices(int priorityFilterFlags, bool filterByProto) const {
    Vector<String16> services = sm_->listServices(priorityFilterFlags);//通過sm獲取服務(wù)集合
    services.sort(sort_func);//集合排序
    ...
    return services;
}

5.3.3.4 打印支持服務(wù)列表

在獲取了服務(wù)集合后,會先檢查服務(wù)是否存在,接著打印服務(wù)的名稱,且如果當(dāng)前指令設(shè)置了"-l"參數(shù),僅打印服務(wù)集合,即流程結(jié)束。

@frameworks\native\cmds\dumpsys\dumpsys.cpp
int Dumpsys::main(int argc, char* const argv[]) {
    ...
    const size_t N = services.size();//獲取支持的服務(wù)個數(shù)
    if (N > 1 || showListOnly) {
        // first print a list of the current services
        std::cout << "Currently running services:" << std::endl;
        for (size_t i=0; i<N; i++) {
            sp<IBinder> service = sm_->checkService(services[i]);//檢查服務(wù)狀態(tài)
            if (service != nullptr) {
                bool skipped = IsSkipped(skippedServices, services[i]);
                std::cout << "  " << services[i] << (skipped ? " (skipped)" : "") << std::endl;//打印服務(wù)名稱
            }
        }
    }
    if (showListOnly) {//如果指令僅需要打印服務(wù)集合,則結(jié)束。
        return 0;
    }
    ...
}

5.3.3.5 打印目標(biāo)服務(wù)

先遍歷所有需要打印的服務(wù),如果參數(shù)有指定服務(wù)名,即N為對應(yīng)服務(wù)的數(shù)量,否則N為所有支持的服務(wù)數(shù)量。接著,開啟線程,通過servicemanager調(diào)用遠(yuǎn)端的dump函數(shù),利用管道和poll機制監(jiān)聽遠(yuǎn)端數(shù)據(jù)。最后如果超時或者dump結(jié)束,則關(guān)閉線程,釋放相關(guān)資源。

@frameworks\native\cmds\dumpsys\dumpsys.cpp
int Dumpsys::main(int argc, char* const argv[]) {
    ...
    for (size_t i = 0; i < N; i++) {
        const String16& serviceName = services[i];
        if (IsSkipped(skippedServices, serviceName)) continue;//跳過部分服務(wù)
        if (startDumpThread(type, serviceName, args) == OK) {//step 1.創(chuàng)建dump打印的線程
            ...
            std::chrono::duration<double> elapsedDuration;
            size_t bytesWritten = 0;
            status_t status =
                writeDump(STDOUT_FILENO, serviceName, std::chrono::milliseconds(timeoutArgMs),
                          asProto, elapsedDuration, bytesWritten);//step 2.dump執(zhí)行打印操作
            if (status == TIMED_OUT) {//打印超時
                std::cout << std::endl
                     << "*** SERVICE '" << serviceName << "' DUMP TIMEOUT (" << timeoutArgMs
                     << "ms) EXPIRED ***" << std::endl
                     << std::endl;
            }
            ...
            bool dumpComplete = (status == OK);
            stopDumpThread(dumpComplete);//step 3.結(jié)束dump打印線程
        }
    }
    ...
}

step 1. 創(chuàng)建dumpsys打印線程
創(chuàng)建了一條管道,接著開啟了一個線程,通過ServiceManager對象讀取目標(biāo)服務(wù)的dump函數(shù),即dump打印數(shù)據(jù)。

@frameworks\native\cmds\dumpsys\dumpsys.cpp
status_t Dumpsys::startDumpThread(Type type, const String16& serviceName,
                                  const Vector<String16>& args) {
    sp<IBinder> service = sm_->checkService(serviceName);//通過SM獲取service對象
    int sfd[2];
    if (pipe(sfd) != 0) {//創(chuàng)建管道,用于讀取service端數(shù)據(jù)
        ...
    }
    ...
    redirectFd_ = unique_fd(sfd[0]);
    unique_fd remote_end(sfd[1]);
    sfd[0] = sfd[1] = -1;
    // dump blocks until completion, so spawn a thread..
    activeThread_ = std::thread([=, remote_end{std::move(remote_end)}]() mutable {//創(chuàng)建線程
        status_t err = 0;
        switch (type) {
        case Type::DUMP:
            err = service->dump(remote_end.get(), args);//調(diào)用dump函數(shù)
            break;
        ...
        }
        ...
    });
    return OK;
}

step 2. dumpsys打印到終端
通過poll機制用來監(jiān)聽管道的數(shù)據(jù),并將讀取到的dump數(shù)據(jù),打印至控制臺。同時,通過計算剩余的時間,來判斷當(dāng)前是否讀取超時。

@frameworks\native\cmds\dumpsys\dumpsys.cpp
status_t Dumpsys::writeDump(int fd, const String16& serviceName, std::chrono::milliseconds timeout,
                            bool asProto, std::chrono::duration<double>& elapsedDuration,
                            size_t& bytesWritten) const {
    ...
    int serviceDumpFd = redirectFd_.get();
    struct pollfd pfd = {.fd = serviceDumpFd, .events = POLLIN};
    while (true) {
        ...
        int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));//poll機制檢測管道數(shù)據(jù)
        if (rc < 0) {
           ...
        } else if (rc == 0 || time_left_ms() == 0) {
            status = TIMED_OUT;//計算剩余時間,來決定是否超時
            break;
        }
        char buf[4096];
        rc = TEMP_FAILURE_RETRY(read(redirectFd_.get(), buf, sizeof(buf)));//讀取遠(yuǎn)端的數(shù)據(jù)
        ...
        if (!WriteFully(fd, buf, rc)) {//打印至控制臺
            ...
            break;
        }
        totalBytes += rc;
    }
    ...
    return status;
}

step 3. 關(guān)閉dumpsys打印線程
將dumpsys打印的線程detach掉,相關(guān)的fd句柄reset掉,釋放資源。

六、dumpsys的應(yīng)用

如后續(xù)有什么應(yīng)用dumpsys,或者有助于日常開發(fā)調(diào)試的場景,再補充,未完待續(xù)。

6.1 dumpsys常用指令

服務(wù)名類名指令功能
activityActivityManagerService獲取某個應(yīng)用的Activity信息:
adb shell dumpsys activity a packagename
獲取某個應(yīng)用的Service信息:
adb shell dumpsys activity s packagename
獲取某個應(yīng)用的Broadcast信息:
adb shell dumpsys activity b packagename
獲取某個應(yīng)用的Provider信息:
adb shell dumpsys activity prov packagename
獲取某個應(yīng)用的進程狀態(tài):
adb shell dumpsys activity p packagename
獲取當(dāng)前界面的Activity信息:
adb shell dumpsys activity top | grep ACTIVITY
AMS相關(guān)信息
packagePackageManagerServiceadb shell dumpsys packagePMS相關(guān)信息
windowWindowManagerServiceadb shell dumpsys windowWMS相關(guān)信息
inputInputManagerServiceadb shell dumpsys inputIMS相關(guān)信息
powerPowerManagerServiceadb shell dumpsys powerPMS相關(guān)信息
batterystatsBatterystatsServiceadb shell dumpsys batterystats電池統(tǒng)計信息
batteryBatteryServiceadb shell dumpsys battery電池信息
alarmAlarmManagerServiceadb shell dumpsys alarm鬧鐘信息
dropboxDropboxManagerServiceadb shell dumpsys dropbox調(diào)試相關(guān)
procstatsProcessStatsServiceadb shell dumpsys procstats進程統(tǒng)計
cpuinfoCpuBinderadb shell dumpsys cpuinfoCPU
meminfoMemBinderadb shell dumpsys meminfo內(nèi)存
gfxinfoGraphicsBinderadb shell dumpsys gfxinfo圖像
dbinfoDbBinderadb shell dumpsys dbinfo數(shù)據(jù)庫

七、參考資料

dumpsys指令介紹:
https://developer.android.google.cn/studio/command-line/dumpsys?hl=zh-cn
管道:
https://www.cnblogs.com/naray/p/15365954.html
Binder:
https://blog.csdn.net/shenxiaolinil/article/details/128972302

到此這篇關(guān)于Android dumpsys簡介的文章就介紹到這了,更多相關(guān)Android dumpsys內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論