深入理解init_4``````````init控制service(基于Android2.2,代码源自Google)
2017-03-06 11:40
726 查看
深入理解init_4“““`init控制service
先看service是如何启动的1、启动zygote
init.rc 中有这样一句话: #class_start 是一个COMMAND,对应的处理函数为do_class_start,它位于boot_section的范围内,为什么说它很重要呢! 还记得init进程中四个执行阶段吗?当init执行下面几句话时,do_class_start就会被执行。 //将boot section 的command加入到执行队列。 action_for_each_trigger(“boot”,action_add_queue_tail); //执行队列里的命令,class是一个COMMAND,所以他对应的do_class_start会被执行。 drain_action_queue();
下面来看do_class_start函数;
2、跳到builtins.c文件
2.1、文件位置
/system/core/init/builtins.c2.2、关键代码分析
int do_class_start(int nargs, char **args) { /*args为do_class_start的参数,init.rc中只有一个参数,就是default。下面这个函数将从service_list中找到classname为”default“的service,然后调用service_start_if_not_disabled函数,现在大家明白classname的作用了吧。 */ /* 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; }
我们已经知道,zygote这个service的classname的值就是“default”,所以会针对service调用service_start_if_not_disabled,这个函数代码:
3、跳到parser.c文件
3.1、文件位置
/system/core/init/parser.c3.2、关键代码分析
static void service_start_if_not_disabled(struct service *svc) { if (!(svc->flags & SVC_DISABLED)){ service_start(svc,NULL); //zygote 可不设置 SVC_DISABLED } }
service_start 函数代码如下:
4、跳转到init.c文件
4.1、文件位置
/system/core/init/init.c4.2、关键代码分析
void service_start(struct service *svc, const char *dynamic_args) { struct stat s; pid_t pid; int needs_console; int n; /* starting a service removes it from the disabled * state and immediately takes it out of the restarting * state if it was in there */ svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING)); svc->time_started = 0; /* running processes require no additional work -- if * they're in the process of exiting, we've ensured * that they will immediately restart on exit, unless * they are ONESHOT */ if (svc->flags & SVC_RUNNING) { return; //如果这个service已经运行,则不进行处理 } needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0; if (needs_console && (!have_console)) { ERROR("service '%s' requires console\n", svc->name); svc->flags |= SVC_DISABLED; return; } /*service 一般运行于另外一个进程中,这个进程也是init的子进程,所以启动service之前判断对应的可执行文件是否存在,zygote 对应的可执行文件是 /system/bin/app_process。 */ if (stat(svc->args[0], &s) != 0) { ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name); svc->flags |= SVC_DISABLED; return; } if ((!(svc->flags & SVC_ONESHOT)) && dynamic_args) { ERROR("service '%s' must be one-shot to use dynamic args, disabling\n", svc->args[0]); svc->flags |= SVC_DISABLED; return; } NOTICE("starting '%s'\n", svc->name); pid = fork(); //调用fork创建子进程 if (pid == 0) { //pid为0,表示现在运行在子进程中 struct socketinfo *si; struct svcenvinfo *ei; char tmp[32]; int fd, sz; //得到属性存储空间的信息并加到环境变量之中,后面在属性服务的一节会碰到使用它的地方。 get_property_workspace(&fd, &sz); sprintf(tmp, "%d,%d", dup(fd), sz); add_environment("ANDROID_PROPERTY_WORKSPACE", tmp); //添加环境变量信息 for (ei = svc->envvars; ei; ei = ei->next) add_environment(ei->name, ei->value); //根据socketinfo创建socket for (si = svc->sockets; si; si = si->next) { int s = create_socket(si->name, !strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_STREAM, si->perm, si->uid, si->gid); if (s >= 0) { //在环境变量中添加socket信息 publish_socket(si->name, s); } } if (svc->ioprio_class != IoSchedClass_NONE) { if (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) { ERROR("Failed to set pid %d ioprio = %d,%d: %s\n", getpid(), svc->ioprio_class, svc->ioprio_pri, strerror(errno)); } } if (needs_console) { setsid(); open_console(); } else { zap_stdio(); } #if 0 for (n = 0; svc->args ; n++) { INFO("args[%d] = '%s'\n", n, svc->args ); } for (n = 0; ENV ; n++) { INFO("env[%d] = '%s'\n", n, ENV ); } #endif //设置uid,gid setpgid(0, getpid()); /* as requested, set our gid, supplemental gids, and uid */ if (svc->gid) { setgid(svc->gid); } if (svc->nr_supp_gids) { setgroups(svc->nr_supp_gids, svc->supp_gids); } if (svc->uid) { setuid(svc->uid); } if (!dynamic_args) { /*执行 /system/bin/app_PROCESS,这样就进入到app_process的main函数中,fork,execve,这两个函数都是linux系统上常用的系统调用。*/ if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) { ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno)); } } else { char *arg_ptrs[SVC_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 == SVC_MAXARGS) break; } arg_ptrs[arg_idx] = '\0'; execve(svc->args[0], (char**) arg_ptrs, (char**) ENV); } _exit(127); } if (pid < 0) { ERROR("failed to start '%s'\n", svc->name); svc->pid = 0; return; } //父进程init的处理,设置service的信息,如启动时间,进程号,以状态信息 svc->time_started = gettime(); svc->pid = pid; svc->flags |= SVC_RUNNING; //每一个service都有一个属性,zygote的属性为init,svc,zygote,现在设置它的值为running notify_service_state(svc->name, "running"); }
原来,zygote是通过fork和execv共同创建,但是service结构体中的那个onrestart好像没有起到作用,为什么呢?
重启zygote,根据名字我们就可以猜到onrestart是在zygote重启时用的,下面在zygote死后,他的父进程init会有什么动作呢。
5、跳到init.rc
5.1、文件位置
/system/core/init/init.c5.2、关键代码分析
static void sigchld_handler(int s) { //当子进程被退出时,init的这个信号处理函数会被调用 write(signal_fd, &s, 1); }
signal_fd,就是在init中通过socketpair创建两个socket中的一个,既然会向socket_fd发送数据,那么另外一个socket就一定能接受到,那样就导致init从poll函数中返回,代码如下:
6、跳到init.r文件
6.1、文件位置
/system/core/init/init.c6.2、关键代码分析
nr = poll(ufds, fd_count, timeout); //调用poll等待一些事情的发生 if (nr <= 0) continue; //ufds[2]保存的是signal_recv_fd,用于接收来自socket的消息。 if (ufds[2].revents == POLLIN) { /* we got a SIGCHLD - reap and restart as needed */ //有一个子进程去世,init要处理这个事情 read(signal_recv_fd, tmp, sizeof(tmp)); while (!wait_for_one_process(0)) //调用wait_for_one_process函数处理 ; continue; }
跳转至wait_for_one_process函数处理
//直接看这个wait_for_one_process函数 static int wait_for_one_process(int block) { pid_t pid; int status; struct service *svc; struct socketinfo *si; time_t now; struct listnode *node; struct command *cmd; while ( (pid = waitpid(-1, &status, block ? 0 : WNOHANG)) == -1 && errno == EINTR ); if (pid <= 0) return -1; INFO("waitpid returned pid %d, status = %08x\n", pid, status); //找到死掉的那个service,现在应该找到代表了zygote的那个service svc = service_find_by_pid(pid); if (!svc) { ERROR("untracked pid %d exited\n", pid); return 0; } NOTICE("process '%s', pid %d exited\n", svc->name, pid); if (!(svc->flags & SVC_ONESHOT)) { //杀掉zygote创建的所有子进程,这就是为什么zygote死后,java世界崩溃的原因。 kill(-pid, SIGKILL); NOTICE("process '%s' killing any children in process group\n", svc->name); } /* remove any sockets we may have created */ //清理socket信息 for (si = svc->sockets; si; si = si->next) { char tmp[128]; snprintf(tmp, sizeof(tmp), ANDROID_SOCKET_DIR"/%s", si->name); unlink(tmp); } svc->pid = 0; svc->flags &= (~SVC_RUNNING); /* oneshot processes go into the disabled state on exit */ if (svc->flags & SVC_ONESHOT) { svc->flags |= SVC_DISABLED; } /* disabled processes do not get restarted automatically */ if (svc->flags & SVC_DISABLED) { notify_service_state(svc->name, "stopped"); return 0; } now = gettime(); /*如果设置了SVC_CRITICAL标志,则4分钟内该服务重启的次数不能超过4次,否则机器会在重启时进入recovery模式。根据init.rc的配置来看,只有在servicemanager进程享有次种待遇*/ if (svc->flags & SVC_CRITICAL) { if (svc->time_crashed + CRITICAL_CRASH_WINDOW >= now) { if (++svc->nr_crashed > CRITICAL_CRASH_THRESHOLD) { ERROR("critical process '%s' exited %d times in %d minutes; " "rebooting into recovery mode\n", svc->name, CRITICAL_CRASH_THRESHOLD, CRITICAL_CRASH_WINDOW / 60); sync(); __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, "recovery"); return 0; } } else { svc->time_crashed = now; svc->nr_crashed = 1; } } svc->flags |= SVC_RESTARTING; /* Execute all onrestart commands for this service. */ //设置标志为svc_RESTARTING,然后执行该service onrestart中的COMMAND list_for_each(node, &svc->onrestart.commands) { cmd = node_to_item(node, struct command, clist); cmd->func(cmd->nargs, cmd->args); } //设置init.svc.zygote的值为restarting. notify_service_state(svc->name, "restarting"); return 0; } 通过上面的代码我们可以知道onrestatrt的作用了,但是zygote本身又在哪里重启呢,我们看下面代码: for(;;) { int nr, i, timeout = -1; for (i = 0; i < fd_count; i++) ufds[i].revents = 0; //在循环中执行动作 drain_action_queue();//poll函数返回后会进入下一个循环 restart_processes(); //这里会重启所有flag标志为svc_RESTARTING的service if (process_needs_restart) { timeout = (process_needs_restart - gettime()) * 1000; if (timeout < 0) timeout = 0; }
这样zygote又回来了。
文档参考:
整理抄录自 — 《深入理解Android卷1》,邓凡平著。
相关文章推荐
- 深入理解init_3 --------- 解析Zygote 的service(基于源码2.2,代码源自Google)
- 深入理解init_5-----属性服务(基于Android 2.2,代码源自Google)
- 深入理解init_2-----解析配置文件init.rc(基于Android 2.2,代码源于Google)
- 深入理解init_1----init分析(基于Android 2.2,源码来自Google)
- 《深入理解Android 卷1》读书笔记 (一)—— Android Init之属性服务 (property_service)
- 深入理解Android的startservice和bindservice
- 深入理解Android的startservice和bindservice
- 基于ffmpeg的Android 2.2播放器开源代码
- 深入理解Android 中的init
- 深入理解Android的startservice和bindservice
- [深入理解Android卷一全文-第三章]深入理解init
- 基于ffmpeg的Android 2.2播放器开源代码
- csdn 深入理解Android》导读之init
- 《深入理解Android 卷1》读书笔记 (一)—— Android Init之zygote restart
- 深入理解Android(03)——深入理解init初始化函数
- 【转】深入理解Android的startservice和bindservice--不错
- 基于android手机的3G+GPS远程控制模型车工程-android手机编程7-伪视频控制远程手机端程序(代码篇)
- 深入理解 GNU GRUB - 02 boot.S 2.2 MBR结构 2.3 boot.S代码结构
- 基于Google的嵌入式系统android开发语音技术(语音搜索,语音朗读文章,语音控制)
- 深入理解Android的startservice和bindservice