查看系统是怎么做到守护进程的
什么系统关键服务 系统的关键服务的ppid也就是父进程都是为1的
闹钟 LayoutInflater WindowManager 不是
网络服务,多媒体服务 ,音量服务,安装服务。 电话服务,adb服务 ,触摸事件服务
netd 网络服务 封装了复杂的底层各种类型的网络
mediaservice 多媒体服务 手机开机需要声音,画面
ueventd 屏幕响应事件的服务
ueventd 屏幕响应事件的服务
事件分发 activity ondispatchevent()
logd 日志服务
vold 外部存储设备服务 管理和控制Android平台外部存储设备,包括SD插拨、挂载、卸载、格式化等;
Rild 是电话系统的核心部分
进入adb shell 命令执行ps查看进程的消息
源码分析,我们这里采用的6.0的源码
首先我们知道,系统在启动的时候,首先会去加载一个文件,为init文件,利用as,可以查看到,可以发现他的权限是有x的,代表是一个可以执行的文件
init可以执行的文件是通过下面的源码路径来编译的 F:\AndroidSource\android-6.0.0_r1\android-6.0.0_r1\system\core ,core目录下面还有很多可以执行的文件比如adb
既然是一个可以执行的文件,那么肯定有一个文件还有main函数的入口,这里main函数的入口即为init.cpp文件中
int main(int argc, char** argv) {
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}
......
init_parse_config_file("/init.rc");
.....
}
查看这个函数的实现 init_parse_config_file("/init.rc");
这个文件里面有很多类似这样的,来声明配置一个服务,
我们能不能获取root权限后 通过修改init.rc配置文件 启动 自己的服务呢?
即使有了root权限,可以修改该文件也没有。因为我们在根目录看到的文件只是内存文件的镜像。也就是说,android启动后,会将init.rc文件装载到内存。
而修改init.rc文件的内容实际上只是修改内存中的init.rc文件的内容。一旦重启android,init.rc文件的内容又会恢复到最初的装载。
想彻底修改init.rc文件内容的唯一方式是修改Android的ROM中的内核镜像(boot.img)。其实boot.img名为内核镜像,有一个镜像ramdisk.img就包含了init.rc文件和init命令。
所以只有修改ramdisk.img文件中的init.rc文件,并且重新打包boot.img文件,并刷机,才能彻底修改init.rc文件。将Android源代码,编译后,
就会看到out目录中的相关子目录会生成一个root目录,该目录实际上就是ramdisk.img解压后的内容。会看到有init命令和init.rc文件。通过简单的修改init.rc文件是达不到的
service netd /system/bin/netd
class main
socket netd stream 0660 root system
socket dnsproxyd stream 0660 root inet
socket mdns stream 0660 root system
此函数中有 parse_config(path, data);
static void parse_config(const char *fn, const std::string& data)
{
struct listnode import_list;
struct listnode *node;
......
for (;;) {
switch (next_token(&state)) {
case T_EOF:
state.parse_line(&state, 0, 0);
goto parser_done;
case T_NEWLINE:
state.line++;
if (nargs) {
int kw = lookup_keyword(args[0]);
if (kw_is(kw, SECTION)) {
state.parse_line(&state, 0, 0);
parse_new_section(&state, kw, nargs, args);
} else {
state.parse_line(&state, nargs, args);
}
nargs = 0;
}
break;
case T_TEXT:
if (nargs < INIT_PARSER_MAXARGS) {
args[nargs++] = state.text;
}
break;
}
}
....
}
int kw = lookup_keyword(args[0]); 是根据第一个的字符,得到对应的函数
比如init.rc文件中的
on nonencrypted
class_start late_start
service drm /system/bin/drmserver
class main
user drm
group drm system inet drmrpc
static int lookup_keyword(const char *s) 其中的s就代表的是第二行的内容 比如这里是 class_start class main 注意这里的class main 跟class_start是一样的
{
switch (*s++) {
case 'b':
if (!strcmp(s, "ootchart_init")) return K_bootchart_init;
break;
case 'c':
if (!strcmp(s, "opy")) return K_copy;
if (!strcmp(s, "lass")) return K_class;
if (!strcmp(s, "lass_start")) return K_class_start;
if (!strcmp(s, "lass_stop")) return K_class_stop;
if (!strcmp(s, "lass_reset")) return K_class_reset;
if (!strcmp(s, "onsole")) return K_console;
if (!strcmp(s, "hown")) return K_chown;
if (!strcmp(s, "hmod")) return K_chmod;
if (!strcmp(s, "ritical")) return K_critical;
break
....
}
所以上面会返回一个K_class_start,而k_class_start为 KEYWORD(class_start, COMMAND, 1, do_class_start) 也就为 do_class_start,是一个函数指针
int do_class_start(int nargs, char **args)
{
/* Starting a class does not start services
* which are explicitly disabled. They must
* be started individually.
*/
service_for_each_class(args[1], service_start_if_not_disabled);
return 0;
}
然后执行 parse_new_section(&state, kw, nargs, args);
static void parse_new_section(struct parse_state *state, int kw,
int nargs, char **args)
{
printf("[ %s %s ]\n", args[0],
nargs > 1 ? args[1] : "");
switch(kw) {
case K_service: 对应的init.rc文件中的service开头的
state->context = parse_service(state, nargs, args);
if (state->context) {
state->parse_line = parse_line_service;
return;
}
break;
case K_on: 对应的init.rc 文件中的 on 开头的
state->context = parse_action(state, nargs, args);
if (state->context) {
state->parse_line = parse_line_action;
return;
}
break;
case K_import: 对应的init.rc 文件中的 import 开头的
parse_import(state, nargs, args);
break;
}
state->parse_line = parse_line_no_op;
}
parse_service(state,nargs,args);函数实现
static void *parse_service(struct parse_state *state, int nargs, char **args)
{
......
从service集合里面查找如果查找到了直接返回
service* svc = (service*) service_find_by_name(args[1]);
if (svc) {
parse_error(state, "ignored duplicate definition of service '%s'\n", args[1]);
return 0;
}
nargs -= 2;
如果没有查找到就new 一个service 分配内存空间
svc = (service*) calloc(1, sizeof(*svc) + sizeof(char*) * nargs);
if (!svc) {
parse_error(state, "out of memory\n");
return 0;
}
给service 赋值
svc->name = strdup(args[1]);
svc->classname = "default";
memcpy(svc->args, args + 2, sizeof(char*) * nargs);
trigger* cur_trigger = (trigger*) calloc(1, sizeof(*cur_trigger));
svc->args[nargs] = 0;
svc->nargs = nargs;
list_init(&svc->onrestart.triggers);
cur_trigger->name = "onrestart";
list_add_tail(&svc->onrestart.triggers, &cur_trigger->nlist);
执行下面的代码就会给 serivce 中的action 中的 command 里面的 int (*func)(int nargs, char **args); 这个成员变量赋值为通过lookup_keyword 返回的那个函数指针
list_init(&svc->onrestart.commands);
list_add_tail(&service_list, &svc->slist);
return svc;
}
解析完init.rc文件之后
init.rc main函数中还有这样的,下面的是用来解析不是配置在init.rc文件中的服务的
queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done"); 第一个参数就为一个函数指针
void queue_builtin_action(int (*func)(int nargs, char **args), const char *name)
{
action* act = (action*) calloc(1, sizeof(*act));
trigger* cur_trigger = (trigger*) calloc(1, sizeof(*cur_trigger));
cur_trigger->name = name;
list_init(&act->triggers);
list_add_tail(&act->triggers, &cur_trigger->nlist);
list_init(&act->commands);
list_init(&act->qlist);
command* cmd = (command*) calloc(1, sizeof(*cmd));
给入口函数赋值
cmd->func = func;
cmd->args[0] = const_cast<char*>(name);
cmd->nargs = 1;
list_add_tail(&act->commands, &cmd->clist);
添加到servic列表里面
list_add_tail(&action_list, &act->alist);
action_add_queue_tail(act);
}
等上面的serive所有都解析完之后,init main 函数中还有
while (true) {
if (!waiting_for_exec) {
启动服务
execute_one_command();
restart_processes();
}
execute_one_command()中含有下面的代码,获取第一个的service,然后从这个service里面获取到第一个command,赋值给cur_command
if (!cur_action || !cur_command || is_last_command(cur_action, cur_command)) {
cur_action = action_remove_queue_head();
cur_command = NULL;
if (!cur_action) {
return;
}
build_triggers_string(name_str, sizeof(name_str), cur_action);
INFO("processing action %p (%s)\n", cur_action, name_str);
cur_command = get_first_command(cur_action);
} else {
cur_command = get_next_command(cur_action, cur_command);
}
然后执行这个函数,这个就会执行到解析到service里面的func 函数指针比如
int result = cur_command->func(cur_command->nargs, cur_command->args);
比如上面的queue_builtin_action(keychord_init_action, "keychord_init"); 这里的func为,执行对应的函数的初始话操作
void keychord_init() {
service_for_each(add_service_keycodes);
// Nothing to do if no services require keychords.
if (!keychords) {
return;
}
keychord_fd = TEMP_FAILURE_RETRY(open("/dev/keychord", O_RDWR | O_CLOEXEC));
if (keychord_fd == -1) {
ERROR("could not open /dev/keychord: %s\n", strerror(errno));
return;
}
int ret = write(keychord_fd, keychords, keychords_length);
if (ret != keychords_length) {
ERROR("could not configure /dev/keychord %d: %s\n", ret, strerror(errno));
close(keychord_fd);
}
free(keychords);
keychords = nullptr;
register_epoll_handler(keychord_fd, handle_keychord);
}
执行 restart_processes();
static void restart_processes()
{
process_needs_restart = 0;
service_for_each_flags(SVC_RESTARTING,restart_service_if_needed);restart_service_if_needed 为函数指针
}
void service_for_each_flags(unsigned matchflags,
void (*func)(struct service *svc))
{
struct listnode *node;
struct service *svc;
list_for_each(node, &service_list) {
svc = node_to_item(node, struct service, slist);
if (svc->flags & matchflags) {
func(svc); 即会回调传递过来的函数指针,即restart_service_if_needed
}
}
}
函数指针的实现为
static void restart_service_if_needed(struct service *svc)
{
time_t next_start_time = svc->time_started + 5;
if (next_start_time <= gettime()) {
svc->flags &= (~SVC_RESTARTING);
service_start(svc, NULL); 开启服务
return;
}
if ((next_start_time < process_needs_restart) ||
(process_needs_restart == 0)) {
process_needs_restart = next_start_time;
}
}
service_start(svc, NULL); 开启服务 函数实现
void service_start(struct service *svc, const char *dynamic_args)
{
也是通过fork一个子进程,在子进程里面启动这个服务,至此服务被启动完成,这里没有看到守护进程的代码,这里需要了解的是
fork一个进程 会让子进程跟父进程拥有同样的资源,所以可能父进程里面有处理
pid_t pid = fork();
if (pid == 0) {
struct socketinfo *si;
struct svcenvinfo *ei;
char tmp[32];
int fd, sz;
char *arg_ptrs[INIT_PARSER_MAXARGS+1];
int arg_idx = svc->nargs;
char *tmp = strdup(dynamic_args);
char *next = tmp;
char *bword;
/* Copy the static arguments */
memcpy(arg_ptrs, svc->args, (svc->nargs * sizeof(char *)));
while((bword = strsep(&next, " "))) {
arg_ptrs[arg_idx++] = bword;
if (arg_idx == INIT_PARSER_MAXARGS)
break;
}
rg_ptrs[arg_idx] = NULL;
execve(svc->args[0], (char**) arg_ptrs, (char**) ENV); 通过这个可执行的命令启动一个服务execve
}
}
在init.cpp 文件中的main方法中有这样的代码
signal_handler_init();
property_load_boot_defaults();
start_property_service();
signal_handler_init(); 函数的实现
void signal_handler_init() {
// Create a signalling mechanism for SIGCHLD.
int s[2];
这里创建俩个socket套接字,是一对来的,一个用来做客户端,一个用来做服务端
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, s) == -1) {
ERROR("socketpair failed: %s\n", strerror(errno));
exit(1);
}
给全局的变量赋值
signal_write_fd = s[0];
signal_read_fd = s[1];
// Write to signal_write_fd if we catch SIGCHLD.
struct sigaction act;
memset(&act, 0, sizeof(act));
SIGCHLD_handlerw为一个函数指针,也即是当系统杀死调进程的时候,会回调执行的函数
act.sa_handler = SIGCHLD_handler;
act.sa_flags = SA_NOCLDSTOP;
sigaction(SIGCHLD, &act, 0);
reap_any_outstanding_children();
注册监听
register_epoll_handler(signal_read_fd, handle_signal);
}
handle_signal 为一个函数指针,函数的原型为
static void handle_signal() {
// Clear outstanding requests.
char buf[32];
//从signal_read_fd读取内容,read 会阻塞
read(signal_read_fd, buf, sizeof(buf));
reap_any_outstanding_children();
}
register_epoll_handler函数的实现为
void register_epoll_handler(int fd, void (*fn)()) {
epoll_event ev;
ev.events = EPOLLIN;
将fn 赋值给ev.data.ptr
ev.data.ptr = reinterpret_cast<void*>(fn);
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) {
ERROR("epoll_ctl failed: %s\n", strerror(errno));
}
}
SIGCHLD_handler函数的原型为
static void SIGCHLD_handler(int) {
这里利用 signal_write_fd 客户端的socket套接字直接的发消息,这样我们查看接受的地方
if (TEMP_FAILURE_RETRY(write(signal_write_fd, "1", 1)) == -1) {
ERROR("write(signal_write_fd) failed: %s\n", strerror(errno));
}
}
main函数中的while循环中
epoll_event ev;
int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, timeout));
if (nr == -1) {
ERROR("epoll_wait failed: %s\n", strerror(errno));
} else if (nr == 1) {
((void (*)()) ev.data.ptr)(); 执行回调函数,也就是执行到了handle_signal 这个函数里面,这样当客户端收到了要关闭的进程之后,就主动的发了一个消息,这样服务端就接受到了
}
static void handle_signal() {
// Clear outstanding requests.
char buf[32];
//从signal_read_fd读取内容,read 会阻塞
read(signal_read_fd, buf, sizeof(buf));
reap_any_outstanding_children();
}
然后执行reap_any_outstanding_children
static void reap_any_outstanding_children() {
while (wait_for_one_process()) {
}
}
wait_for_one_process()函数里面有这样的关键代码
// Execute all onrestart commands for this service.
struct listnode* node;
list_for_each(node, &svc->onrestart.commands) {
command* cmd = node_to_item(node, struct command, clist);
执行入口函数
cmd->func(cmd->nargs, cmd->args);
}
服务又再次的被启动
svc->NotifyStateChange("restarting");
return true;
然后main 中的while循环里面就会把这个服务启动
方式二 main函数中有这样的代码
start_property_service();
函数原型实现
void start_property_service() {
创建socket套接字
property_set_fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
0666, 0, 0, NULL);
if (property_set_fd == -1) {
ERROR("start_property_service socket creation failed: %s\n", strerror(errno));
exit(1);
}
监听,8为并发数
listen(property_set_fd, 8);
注册监听
register_epoll_handler(property_set_fd, handle_property_set_fd);handle_property_set_fd为一个函数指针
}
handle_property_set_fd 函数原型的实现为:
static void handle_property_set_fd()
{
监听
if ((s = accept(property_set_fd, (struct sockaddr *) &addr, &addr_size)) < 0) {
return;
}
/* Check socket options here */
if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {
close(s);
ERROR("Unable to receive socket options\n");
return;
}
ufds[0].fd = s;
ufds[0].events = POLLIN;
ufds[0].revents = 0;
.......
handle_control_message((char*) msg.name + 4, (char*) msg.value);
.......
}
handle_control_message()函数原型实现
void handle_control_message(const char *msg, const char *arg)
{
if (!strcmp(msg,"start")) {
msg_start(arg); 启动服务
} else if (!strcmp(msg,"stop")) {
msg_stop(arg);
} else if (!strcmp(msg,"restart")) {
msg_restart(arg);
} else {
ERROR("unknown control msg '%s'\n", msg);
}
}
启动服务
static void msg_start(const char *name)
{
struct service *svc = NULL;
char *tmp = NULL;
char *args = NULL;
if (!strchr(name, ':'))
svc = service_find_by_name(name);
else {
tmp = strdup(name);
if (tmp) {
args = strchr(tmp, ':');
*args = '\0';
args++;
svc = service_find_by_name(tmp);
}
}
if (svc) {
service_start(svc, args); 启动服务
} else {
ERROR("no such service '%s'\n", name);
}
if (tmp)
free(tmp);
}
流程图: