Android7.0 PackageManagerService (5) installd

在之前的博客中已经提到过,当SystemServer创建PKMS时,在其构造函数中传入了一个Installer对象。
Installer是一个系统服务,可以和installd通信,完成一些重要的工作,例如利用dexopt函数对APK文件进行dex优化;存储空间不足时,利用freeCache函数清理存储空间。

接下来,我们就分析一下installd及一些重要工作的流程。

一、installd的初始化
1、installd启动
在init.rc中,有以下代码片段:

.......
service installd /system/bin/installd
    class main
    socket installd stream 600 system system
.......

容易看出installd将作为service被init进程启动,同时会创建一个名为installd的socket。

在frameworks/native/cmds/installd/installd.cpp中:

int main(const int argc, char *argv[]) {
    return android::installd::installd_main(argc, argv);
}

static int installd_main(const int argc ATTRIBUTE_UNUSED, char *argv[]) {
    .........
    //以下初始化全局变量,包括创建data下的一些目录等
    if (!initialize_globals()) {
        ALOGE("Could not initialize globals; exiting.\n");
        exit(1);
    }

    if (initialize_directories() < 0) {
        ALOGE("Could not create directories; exiting.\n");
        exit(1);
    }
    ...........
    //得到"installd" socket
    lsocket = android_get_control_socket(SOCKET_PATH);
    ...........
    //"installd"变成服务端
    if (listen(lsocket, 5)) {
        ALOGE("Listen on socket failed: %s\n", strerror(errno));
        exit(1);
    }
    fcntl(lsocket, F_SETFD, FD_CLOEXEC);

    for (;;) {
        alen = sizeof(addr);
        //接受Java层的installer服务连接,形成与之连接的socket "s"
        s = accept(lsocket, &addr, &alen);
        ..........
        fcntl(s, F_SETFD, FD_CLOEXEC);
        ..........
        for (;;) {
            unsigned short count;
            //读取收到的消息的长度
            if (readx(s, &count, sizeof(count))) {
                ALOGE("failed to read size\n");
                break;
            }

            //判断有效性
            if ((count < 1) || (count >= BUFFER_MAX)) {
                ALOGE("invalid size %d\n", count);
                break;
            }

            //读取cmd
            if (readx(s, buf, count)) {
                ALOGE("failed to read command\n");
                break;
            }
            ..........
            buf[count] = 0;
            //执行cmd
            if (execute(s, buf)) break;
        }
        .........
        close(s);
    }

    return 0;
}

上面的代码中,我们省去了selinux相关的代码,只保留主干。
从主干代码容易看出,installd整体的结构非常简单,其实就是启动后,获取作为服务端的socket “installd”;
然后,监听”installd”,等待Java层installer服务的连接及命令的到来。

2、命令处理方式
一旦installd收到命令后,将调用execute函数进行处理,其代码如下:

static int execute(int s, char cmd[BUFFER_MAX]) {
    char reply[REPLY_MAX];
    char *arg[TOKEN_MAX+1];
    .......
    arg[0] = cmd;
    //解析参数的个数
    while (*cmd) {
        //当发现空格时
        if (isspace(*cmd)) {
            *cmd++ = 0;
            //参数个数+1
            n++;
            //保存参数
            arg[n] = cmd;
            if (n == TOKEN_MAX) {
                ALOGE("too many arguments\n");
                goto done;
            }
        }
        if (*cmd) {
          cmd++;
        }
    }

    //cmds为一个数组,保存了不同命令及对应的处理函数
    for (i = 0; i < sizeof(cmds) / 
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值