探秘Android系统:dumpsys命令获取系统服务详细信息

移动开发 Android
dumpsys是Android系统中的一个可执行文件,主要作用是将当前Android系统的一些信息dump出来,例如Activity、package等。

dumpsys是Android系统中的一个可执行文件,主要作用是将当前Android系统的一些信息dump出来,例如Activity、package等。是一个分析Android设备问题、查看运行状态、使用情况等十分有效的工具。可以获取各种系统信息和状态,如进程的PSS值,分析了解进程对RAM的占用情况。

dumpsys的语法提供了灵活的方式来获取和分析Android系统中各种服务的信息。基本语法结构如下:

adb shell dumpsys [-t timeout] [--help | -l | --skipservices | service[arguments] | -c | -h]
  • [-t timeout]:可选参数,用于指定命令执行的超时时间(以秒为单位)。默认为10秒。
  • [--help | -l | --skipservices | service[arguments] | -c | -h]:命令行选项,用于定制dumpsys的输出和行为。

--help:打印dumpsys的使用方法说明。

-l:列出dumpsys支持的所有系统服务列表。

--skipservices:指定不需要打印的服务列表。

service[arguments]:指定要查询的特定服务及其可选参数。通过指定服务名称,可以获取特定服务的详细信息。

-c:以机器友好的格式(通常是键值对)输出信息,对于自动化脚本解析可能很有用,对于人类阅读可能不太友好。

-h:用在指定的服务后面,打印服务支持哪些参数或如何使用该服务。

% adb shell dumpsys -l
Currently running services:
DisplayFeatureControl
DockObserver
MiuiBackup
MiuiCarService
MiuiInit
MiuiWifiService
ProcessManager
SchedBoostService
SlaveWifiService
SurfaceFlinger
accessibility
account
activity
activity_task
adb

如果dumpsys不加任何参数,会输出所有系统服务的详细信息,输出的内容是非常多的。实际解决具体问题时,我们通常只关注一些特定系统服务的输出,只需要将服务名作为dumpsys命令的参数,就可以只输出特定服务的信息。比如要输出磁盘使用的统计信息,则可以将diskstats这个系统服务名作为参数。

% adb shell dumpsys diskstats
Latency: 1ms [512B Data Write]
Recent Disk Write Speed (kB/s) = 45546
Data-Free: 53243072K / 113006560K total = 47% free
Cache-Free: 53243072K / 113006560K total = 47% free
System-Free: 0K / 5192648K total = 0% free
File-based Encryption: true
App Size: 16656406016
App Data Size: 33915740160
App Cache Size: 2662189568
Photos Size: 77041664
Videos Size: 17559552
Audio Size: 38887424
Downloads Size: 0
System Size: 128000000000
Other Size: 9238536192

工作原理

dumpsys基于Android系统的服务管理和进程间通信机制。通过调用Android系统底层的ServiceManager服务,来获取系统中所有已注册服务的信息。ServiceManager是Android系统中的一个核心服务,负责管理系统中的所有服务,提供统一的注册、发现和通信机制。

当dumpsys被调用时,会通过Binder进程间通信(IPC)框架与ServiceManager进行交互。Binder是Android提供的一套进程间相互通信的框架,允许不同的进程之间进行高效的通信和数据交换。通过Binder,dumpsys能够请求ServiceManager提供当前系统中所有已注册服务的列表,以及每个服务的详细信息。

ServiceManager会响应dumpsys的请求,返回系统中所有服务的状态信息。包括服务的名称、状态、运行时的统计数据等。dumpsys接收到这些信息后,会进行解析和整理,并以一种可读的方式展示。

int main(int argc, char* const argv[])
{
    ...
    // 1. 首先获取 servicemanager
    sp<IServiceManager> sm = defaultServiceManager();
    ...
    // 2. 进行命令行参数解析
    bool showListOnly = false;
    if ((argc == 2) && (strcmp(argv[1], "-l") == 0)) {
        // 2.1 当参数仅为 "-l" 时,设置只罗列出所有的服务名
        showListOnly = true;
    }
    if ((argc == 1) || showListOnly) {
        // 2.2 当不带任何参数时,则附加 "-a" 参数,表示输出所有系统服务信息
        services = sm->listServices();
        services.sort(sort_func);
        args.add(String16("-a"));
    } else {
        // 2.3 当带了一个参数时,表示仅输出指定的系统服务信息
        services.add(String16(argv[1]));
        for (int i=2; i<argc; i++) {
            args.add(String16(argv[i]));
        }
    }

    // 3. 罗列出services这个数组中的服务名称,到这一步为止,都还只是在dumpsys本身的逻辑中转悠
    const size_t N = services.size();
    if (N > 1) {
        aout << "Currently running services:" << endl;    
        for (size_t i=0; i<N; i++) {
            sp<IBinder> service = sm->checkService(services[i]);
            if (service != NULL) {
                aout << "  " << services[i] << endl;
            }
        }
    }
    if (showListOnly) {
        return 0;
    }

    // 4. 输出services这个数组中所包含系统服务的详细信息
    for (size_t i=0; i<N; i++) {
        sp<IBinder> service = sm->checkService(services[i]);
        if (service != NULL) {
            ...
            // 4.1 调用service的dump方法,来输出service的具体信息
            int err = service->dump(STDOUT_FILENO, args);
            ...
        }
        ...
    }
    return 0;
}
  1. 获取servicemanager,所有的系统服务都会向servicemanager注册
  2. 进行命令行参数解析,根据参数的不同设置后续的执行指令序列
  3. 简单的罗列了一下需要输出的系统服务名称
  4. 调用具体系统服务的dump()方法完成系统服务详细信息的输出

以上面adb shell dumpsys diskstats命令为例,最终调用dump()方法完成输出:

protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    // 1. 权限检查
    mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);

    // 2. 生成一个大小为512B的临时文件
    byte[] junk = new byte[512];
    for (int i = 0; i < junk.length; i++) junk[i] = (byte) i;  // Write nonzero bytes
    File tmp = new File(Environment.getDataDirectory(), "system/perftest.tmp");

    // 3. 将512B的临时文件写入磁盘,目的是为了快速的测试写磁盘的延迟
    long before = SystemClock.uptimeMillis();
    ...
    fos = new FileOutputStream(tmp);
    fos.write(junk);
    ...
    long after = SystemClock.uptimeMillis();
    ...
    pw.print("Latency: ");
    pw.print(after - before);
    pw.println("ms [512B Data Write]");
    ...
    // 4. 输出Data, Cache和System这几个分区的磁盘使用信息
    reportFreeSpace(Environment.getDataDirectory(), "Data", pw);
    reportFreeSpace(Environment.getDownloadCacheDirectory(), "Cache", pw);
    reportFreeSpace(new File("/system"), "System", pw);
    ....
}

责任编辑:武晓燕 来源: 沐雨花飞蝶
相关推荐

2010-11-09 11:54:50

sql server查

2012-05-14 10:49:25

Cloud Found

2010-02-07 14:54:13

Android

2009-08-07 15:54:51

敏感信息检测系统UnisSISS

2009-07-27 10:48:53

ASP.NET Det

2010-03-03 16:08:20

Android手机系统

2010-09-06 11:57:33

sql server语句

2020-11-17 12:59:34

数据泄露Capcom恶意软件

2016-01-07 13:52:17

Windows 10登录显示

2020-05-15 07:00:00

Linux硬盘信息

2009-10-15 09:58:13

Linux系统信息查看

2021-12-17 14:49:44

Linuxinxi 命令系统信息

2010-03-10 11:15:45

Linux系统网络服务

2019-08-26 11:53:38

Linux系统GUI

2020-09-17 14:57:39

CISA黑客漏洞

2010-01-22 10:54:45

Linux操作系统PS命令

2012-05-04 09:24:02

Linuxps命令

2010-02-06 15:53:55

2013-04-01 16:07:41

2009-12-22 11:09:54

Linux系统
点赞
收藏

51CTO技术栈公众号