源码基于:android R
0. 前言
我们经常在修改framework 重要东西不是直接reboot 平台进行验证,而是使用命令:
stop;start
这样就能达到重启system server 的效果,具体这两个命令是如何执行的?本文来简单分析下。
1. 来源
从平台或者编译后的out 目录下,很轻松地能找到stop 和start 两个可执行文件。
以平台上为例:
lrwxr-xr-x 1 root shell 7 2021-11-01 05:36 start -> toolbox
lrwxr-xr-x 1 root shell 7 2021-11-01 05:36 stop -> toolbox
其实,stop 和start 就是可执行程序toolbox
2. toolbox 的main 程序
源码目录:system/core/toolbox/toolbox.c
#define TOOL(name) int name##_main(int, char**);
int main(int argc, char** argv) {
// Let's assume that none of this code handles broken pipes. At least ls,
// ps, and top were broken (though I'd previously added this fix locally
// to top). We exit rather than use SIG_IGN because tools like top will
// just keep on writing to nowhere forever if we don't stop them.
signal(SIGPIPE, SIGPIPE_handler);
char* cmd = strrchr(argv[0], '/');
char* name = cmd ? (cmd + 1) : argv[0];
for (size_t i = 0; tools[i].name; i++) {
if (!strcmp(tools[i].name, name)) {
return tools[i].func(argc, argv);
}
}
printf("%s: no such tool\n", argv[0]);
return 127;
}
函数很简单,
- 解析下命令行的第一个参数,并去除路径。如果没有路径,那就直接使用命令,例如start;
- 通过数组tools的name 匹配到合适的func 并将参数argc和argv 带入执行;
注意代码最开始的TOOL(name),用以声明函数,而tools数组中的func 就是通过TOOL注册,详细看 system/core/toolbox/toolbox.h:
TOOL(getevent)
TOOL(getprop)
TOOL(modprobe)
TOOL(setprop)
TOOL(start)
TOOL(stop)
TOOL(toolbox)
相当于声明了在toolbox.c 最开始声明了一系列的函数:
int getevent_main(int, char**);
int getprop_main(int, char**);
int modprobe_main(int, char**);
int setprop_main(int, char**);
int start_main(int, char**);
int stop_main(int, char**);
int toolbox_main(int, char**);
我们还可以在toolbox.c 中定义了数组tools:
static struct {
const char* name;
int (*func)(int, char**);
} tools[] = {
#define TOOL(name) { #name, name##_main },
#include "tools.h"
#undef TOOL
{ 0, 0 },
};
转换为:
static struct {
const char* name;
int (*func)(int, char**);
} tools[] = {
{"getevent", getevent_main},
{"getprop", getprop_main},
{"modprobe", modprobe_main},
...
{ 0, 0 },
};
总结:
- 在toolbox.c 声明了一系列 *_main 函数,并将其初始化定义在tools 数组中;
- 每个命令都链接到toolbox,运行toolbox main函数时,根据传入的参数确定 *_main,并执行;
3. start 命令
根据上一节确认start 命令最终会调用到start_main():
extern "C" int start_main(int argc, char** argv) {
return StartStop(argc, argv, true);
}
4. stop 命令
同理,stop 命令最终调用到的是stop_main():
extern "C" int stop_main(int argc, char** argv) {
return StartStop(argc, argv, false);
}
OVER,找到了源头剩下来的代码就简单了,这里不做过多阐述了。根本原理是通过ctl.start 和ctl.stop 来控制service:
std::vector<std::string> services = {
"iorapd",
"netd",
"surfaceflinger",
"audioserver",
"zygote",
};