您的位置:首页 > 移动开发 > Android开发

深入理解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.c

2.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.c

3.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.c

4.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.c

5.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.c

6.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》,邓凡平著。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android