Android启动之init.c文件main函数分析

最后更新于:2022-04-01 15:54:03

源码位置:/syste/core/init/init.c文件 ~~~ int main(int argc, char **argv) { int fd_count = 0; struct pollfd ufds[4]; int property_set_fd_init = 0; int signal_fd_init = 0; int keychord_fd_init = 0; if (!strcmp(basename(argv[0]), "ueventd")) return ueventd_main(argc, argv); init_parse_config_file("/init.rc"); // 解析/init.rc文件 /* pull the kernel commandline and ramdisk properties file in */ import_kernel_cmdline(0, import_kernel_nv); // 从/proc/cmdline获取参数 chmod("/proc/cmdline", 0440); get_hardware_name(hardware, &revision); snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware); // 根据硬件名字,获取对应的rc文件 init_parse_config_file(tmp); // 对于service,这里会为每个服务建立一个struct service结构体,全部加入service_list链表之后,在init的最后循环中按照顺序启动 // 检查解析出的命令行当中是否有early-init阶段的动作,加入到action_queue中,马上执行 // init动作执行分为4个阶段:early-init、init、early-boot、boot action_for_each_trigger("early-init", action_add_queue_tail); // 属性初始化等等 queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done"); queue_builtin_action(property_init_action, "property_init"); queue_builtin_action(keychord_init_action, "keychord_init"); queue_builtin_action(console_init_action, "console_init"); queue_builtin_action(set_init_properties_action, "set_init_properties"); // 触发init阶段的动作 action_for_each_trigger("init", action_add_queue_tail); // 如果是充电启动,则跳过下面这些动作 if (strcmp(bootmode, "charger") != 0) { action_for_each_trigger("early-fs", action_add_queue_tail); action_for_each_trigger("fs", action_add_queue_tail); action_for_each_trigger("post-fs", action_add_queue_tail); action_for_each_trigger("post-fs-data", action_add_queue_tail); } // 启动属性服务,加载属性文件 queue_builtin_action(property_service_init_action, "property_service_init"); // 信号处理这里会通过socketpair创建两个socket套接字,一个用于接收,一个用于发送 queue_builtin_action(signal_init_action, "signal_init"); // 检查开机状况 queue_builtin_action(check_startup_action, "check_startup"); if (!strcmp(bootmode, "charger")) { action_for_each_trigger("charger", action_add_queue_tail); } else { // 触发early-boot和boot阶段的动作 action_for_each_trigger("early-boot", action_add_queue_tail); action_for_each_trigger("boot", action_add_queue_tail); } // 启动所有依赖于当前时间属性的操作,即:启动那些根据属性值来判断是否执行的动作 queue_builtin_action(queue_property_triggers_action, "queue_propety_triggers"); for(;;) { int nr, i, timeout = -1; // 循环中执行动作,并重启那些死去的进程 execute_one_command(); restart_processes(); // init 处理来自三个方面的消息 if (!property_set_fd_init && get_property_set_fd() > 0) { ufds[fd_count].fd = get_property_set_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; property_set_fd_init = 1; } if (!signal_fd_init && get_signal_fd() > 0) { ufds[fd_count].fd = get_signal_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; signal_fd_init = 1; } if (!keychord_fd_init && get_keychord_fd() > 0) { ufds[fd_count].fd = get_keychord_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; keychord_fd_init = 1; } if (process_needs_restart) { timeout = (process_needs_restart - gettime()) * 1000; if (timeout < 0) timeout = 0; } if (!action_queue_empty() || cur_action) timeout = 0; nr = poll(ufds, fd_count, timeout); if (nr <= 0) continue; // 处理这三个方面的消息 for (i = 0; i < fd_count; i++) { if (ufds[i].revents == POLLIN) { if (ufds[i].fd == get_property_set_fd()) handle_property_set_fd(); else if (ufds[i].fd == get_keychord_fd()) handle_keychord(); else if (ufds[i].fd == get_signal_fd()) handle_signal(); } } } return 0; } ~~~ **1)解析配置文件:**       根据前面所知,在init中系统会解析两个配置文件,一个是/init.rc系统配置文件,另外一个是与硬件平台相关的配置文件。调用的都是同一个函数: ~~~ int init_parse_config_file(const char*fn) { char*data; data = read_file(fn, 0); if (!data) return -1; parse_config(fn, data); return 0; } struct parse_state { char* ptr; // 读指针 char* text; // 文本 int line; // 第几行 int nexttoken; // 下一个标示符 void* context; void (*parse_line)(struct parse_state* state, int nargs, char**args); // 解析函数 const char* filename; }; static void parse_config(const char *fn, char *s) { struct parse_state state; char *args[INIT_PARSER_MAXARGS]; // 最多64个参数 int nargs; nargs = 0; state.filename = fn; state.line = 0; state.ptr = s; state.nexttoken = 0; state.parse_line = parse_line_no_op; // 设置解析函数,不同内容对应不同的解析函数 for (;;) { switch (next_token(&state)) // 获取配置文件中特殊标识,如文件结尾:T_EOF, 换行符:T_NEWLINE, 文本:T_TEXT { case T_EOF: state.parse_line(&state, 0, 0); return; case T_NEWLINE: state.line++; if (nargs) { int kw = lookup_keyword(args[0]); if (kw_is(kw, SECTION)) { // 判断关键字类型是不是为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; } } } 这里parse_config,首先会找到配置文件的一个section,然后针对不同的section使用不同的解析函数来解析。 下面我们看看关键字的定义:keywords.h文件中 #ifndef KEYWORD // 如果没有定义KEYWORD这个宏 int do_class_start(int nargs, char**args); int do_class_stop(int nargs, char**args); int do_class_reset(int nargs, char**args); ... #define __MAKE_KEYWORD_ENUM__ // 定义一个宏 #define KEYWORD(symbol, flags, nargs, func) K_##symbol, enum { K_UNKNOWN, #endif KEYWORD(class, OPTION, 0, 0) KEYWORD(class_start, COMMAND, 1, do_class_start) KEYWORD(on, SECTION, 0, 0) .... #ifdef __MAKE_KEYWORD_ENUM__ KEYWORD_COUNT, }; #undef __MAKE_KEYWORD_ENUM__ #undef KEYWORD #endif 在parser.c文件中: #define SECTION 0x01 #define COMMAND 0x02 #define OPTION 0x04 #include "keywords.h" // 第一次包含ketwords.h文件,由于没有定义宏KEYWORD所以,相当于: /* int do_class_start(int nargs, char**args); int do_class_stop(int nargs, char**args); int do_class_reset(int nargs, char**args); ... enum { K_UNKNOWN, // 0 K_class, K_class_start, K_on, .... KEYWORD_COUNT, }; 得到了一个枚举的定义 */ // 自己定义了一个宏 #define KEYWORD(symbok, flags, nargs, func) [ K_##symbol ] = {#symbol, func, nargs+1, flags,}, struct { const char* name; // 关键字名字 int (*func)(int args, char**args); // 对应关键字的处理函数 unsigned char nargs; unsigned char flags; // 关键字属性:COMMAND、OPTION、SECTION } keyword_info[KEYWORD_COUNT] = { [ K_UNKNOWN] = {"unknown", 0, 0, 0}, // #include "keyword.h" //第二次包含keywords.h文件,由于已经定义了KEYWORD所以相当于: // KEYWORD(class, OPTION, 0, 0) // KEYWORD(class_start, COMMAND, 1, do_class_start) // KEYWORD(service, SECTION, 0, 0) /***宏替换之后为 ***/ [ K_class ] = {"class", 0, 1, OPTION,}, [ k_class_start ] = {"class_start", do_class_start, 2, COMMAND,}, [ k_service ] = {"service", 0, 1, SECTION}, ..... }; #indef KEYWORD 同时我们还定义了一些辅助的宏: #define kw_is(kw, type) (keyword_info[kw].flags & (type)) #define kw_name(kw) (keyword_info[kw].name) #define kw_func(kw) (keyword_info[kw].func) #define kw_nargs(kw) (keyword_info[kw].nargs) 这样我们就得到了一个全局的数组keyword_info,以前面枚举值为索引,存储对应的关键字信息,包括关键字名称、处理函数、参数个数、属性等等。 下面我们根据上面定义的数组ketword_info来看看init.rc文件,如 Zygote: // service是一个section 的标志,名字为zygote 参数个数为5 service zygote /system/bin/app_process -Xzygote /system/bin -zygote --start-system-server // 下面socket 和 onrestart 都是表示OPTION // write 和 restart都是COMMAND socket zygote stream 666 onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart media 找到section之后我们的入口函数时parse_new_section: void parse_new_section(struct parse_state *state, int kw, int nargs, char **args) { switch(kw) { case K_service: state->context = parse_service(state, nargs, args); if (state->context) { state->parse_line = parse_line_service; return; } break; case K_on: state->context = parse_action(state, nargs, args); if (state->context) { state->parse_line = parse_line_action; return; } break; case K_import: if (nargs != 2) { ERROR("single argument needed for import\n"); } else { int ret = init_parse_config_file(args[1]); if (ret) ERROR("could not import file %s\n", args[1]); } } state->parse_line = parse_line_no_op; } 对于service这里我们看到主要就是调用两个函数:parse_service 和 parse_line_service,在这之前我们首先看看init是怎么组织这些service的。 struct service { struct listnode slist; // 用于将结构体连接成一个双向链表,Init 中有一个全局链表service_list 专门用来保存service const char* name; // service 名字 const char* classname; // 默认 default unsigned char flags; pid_t pid; ... struct socketinfo *sockets; // 保存service用到的socket,也是一个链表 struct svcenvinfo *envvars; // 描述创建这个进程时需要的环境变量信息 struct action onrestart; // 存储command信息 int nargs; // 参数个数 char *nargs[1]; // 存储参数 }; struct action { // 一个action 存放在三个双向链表中,alist 存储所有的action // qlist 存储那些等待执行的action // tlist 存储那些等待某些条件满足后需要执行的action struct listnode alist; struct listnode qlist; struct listnode tlist; unsigned hash; const char* name; struct listnode commands; struct command* current; }; struct command { struct listnode clist; // command 链表 int (*func)(int nargs, char**args); int nargs; char *args[1]; }; //parse_service:创建service对象,解析定义的service行,设置默认class为default static void* parse_service(struct parse_state* state, int nargs, char**args) { struct service *svc; svc = service_find_by_name(argv[1]); // 如果这个服务已经存在 if (svc) return 0; nargs -= 2; svc = calloc(1, sizeof(*svc) + sizeof(char*)*nargs); svc->name = args[1]; svc->classname = "default"; memcpy(svc->args, args+2, sizeof(char*)*nargs); svc->args[nargs] = 0; svc->nargs = nargs; svc->onrestart.name = "onrestart"; list_init(&svc->onrestart.commands); list_add_tail(&service_list, &svc->slist); // 将这个service加到全局链表service_list的尾部 return svc; } // 根据服务名字查找链表 struct service* service_find_by_name(const char*name) { struct listnode* node; struct service* svc; list_for_each(node, &service_list) { svc = node_to_item(node, struct service, slist); if (!strcmp(svc->name, name)) return svc; } /* 宏替换相当于: for(node = service_list->next; node != service_list; node = node->next) { svc = (struct srevice*)(((char*)node) - offsetof(struct service, slist)); // svc = (strcut service*)( ((char*)node) - (size_t)&((struct service)0)->slist) // 就是根据链表中的node找到对应的service结构体 if (!strcmp(svc->name, name)) return svc; } */ return 0; } /* 这里的service_list是一个全局的双向循环链表,static list_declare(service_list);宏替换后为: struct listnode service_list = { .next = &service_lsit, .prev = &service_list,}; */ // 双向链表添加程序 void list_add_tail(struct listnode *head, struct listnode *item) { item->next = head; item->prev = head->prev; head->prev->next = item; head->prev = item; } /* 当添加了3个节点a,b,c到链表之后相当于: service_list->next = a; a->next = b; b->next= c; c->next = service_list; */ //parse_line_service: 解析service中的option static void parse_line_service(struct parse_state* state, int nargs, char**args) { struct service *svc = state->context; struct command* cmd; int i, kw, kw_nargs; svc->ioptro_class = IoSchedClass_NONE; kw = lookup_keyword(args[0]); switch(kw) { case K_capability: break; case K_class: ... case K_onrestart:{ // onrestart write /sys/android_power/request_state wake nargs--; args++; kw = lookup_keyword(args[0]); // 返回K_write 作为索引 if(!kw_id(kw, COMMAND)) break; // 根据前面的keyword_info数组判断write是不是command kw_nargs = kw_nargs(kw); // 判断write需要几个参数 cmd = malloc(sizeof(*cmd) + sizeof(char*)*nargs); cmd->func = kw_func(kw); // 这里应该是do_write函数 cmd->nargs = nargs; // 3 memcpy(cmd->args, args, sizeof(char*)*nargs); // onrestart write /sys/android_power/request_state wake list_add_tail(&svc->onrestart.commands, &cmd->clist); break; } case K_socket: { // socket zygote stream 666 struct socketinfo* si; si = calloc(1, sizeof(*st)); si->name = args[1]; // zygote si->type = args[2]; // stream si->perm = strtoul(args[3], 0, 8); // 666 if(nargs > 4) .... si->next = svc->sockets; // 前向插入到svc->sockets这个链表中 svc->sockets = si; break; } default: psrse_error(""); } } ~~~ 这样通过解析init.rc和init.hardware.rc之后我们将所有的service通过一个全局链表service_list连接起来了,同理将所有action通过一个全局链表action_list连接起来。 **2)判断各个阶段工作开始执行** ~~~ action_for_each_trigger("early-init", action_add_queue_tail); action_for_each_trigger("init", action_add_queue_tail); action_for_each_trigger("early-boot", action_add_queue_tail); action_for_each_trigger("boot", action_add_queue_tail); // 这里我们通过分析early-init为例: void action_for_each_trigger(const char* trigger, void (*func)(struct action* act)) { struct listnode *node; struct action *act; list_for_each(node, &action_list){ act = node_to_item(node, struct action, alist); if(!strcmp(act->name, trigger)) func(act); } } //同前面的service分析,这里通过全局链表action_list,找到对应节点的action,如果节点的名字属性为early-init,执行func这个回调函数。 void action_add_queue_tail(struct action* act) { list_add_tail(&action_queue, &act->qlist); } //我在网上看到很多说上面的action_for_each_trigger函数是执行early-init阶段的action,但是我分析发现:这里也是将这些那些等待执行链表qlist中的action加入到action_queue这个全局链表中,action_queue也是通过宏声明的list_declare(action_queue)。并没有立即执行!!! 同理后面的action_for_each_trigger("init",...)等都是将不同阶段的action加入到action_queue这个链表中。 ~~~ **3)属性服务初始化和信号处理初始化** ~~~ queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done"); queue_builtin_action(property_init_action, "property_init"); queue_builtin_action(keychord_init_action, "keychord_init"); queue_builtin_action(console_init_action, "console_init"); queue_builtin_action(set_init_properties_action, "set_init_properties"); queue_builtin_action(property_service_init_action, "property_service_init"); queue_builtin_action(signale_init_action, "signale_init"); queue_builtin_action(check_startup_action, "check_startup"); queue_builtin_action(queue_property_triggers_action, "queue_property_triggers"); void queue_builtin_action(int (*func)(int nargs, char**args), char *name) { struct action* act; struct command *cmd; act = calloc(1, sizeof(*act)); act->name = name; list_init(&act->commands); // 将这个命令加到action的commands里面 cmd = calloc(1, sizeof(*cmd)); cmd->func = func; cmd->args[0] = name; list_add_tail(&act->commands, &cmd->clist); // 将这个action加到全局链表action_list中去 list_add_tail(&action_list, &act->alist); // 将这个action的等待执行的链表qlist加入到action_queue中 action_add_queue_tail(act); } ~~~ **4)进入死循环执行** ~~~ for(;;) { execute_command(); restart_processes(); for(i = 0; i < fd_count; i++) { if(ufds[i].revents == POLLIN) { if (ufds[i].fd == get_property_set_fd()) handle_property_set_fd(); else if(ufds[i].fd == get_keychord_fd()) handle_keychord(); else if(ufds[i].fd == get_signale_fd()) handle_signale(); } } } // 这里主要关心属性设置、组合按键输入、信号三个事件。 handle_property_set_fd(); handle_keychord(); handle_signale(); ~~~ 下面我们主要来看看execute_command() 函数 和 restart_processes()函数 ~~~ static struct action *cur_action = NULL; static struct command *cur_command = NULL; execute_one_command() { // 第一次进来肯定为NULL if(!cur_action || !cur_command || is_last_command(cur_action, cur_command)) { cur_action = action_remove_queue_head(); // 获得action cur_command = NULL; if (!cur_action) return; cur_command = get_first_command(cur_action); // 根据action获得command } else {// 如果一个action包含多个command的情况就需要多次调用才能执行完成 cur_command = get_next_command(cur_action, cur_command); } if (!cur_command) return; cur_command->func(cur_command->nargs, cur_command->args); // 调用当前command的func函数 } // 从链表action_queue头部开始获取action void action_remove_queue_head() { if(list_empty(&action_queue)) return 0; else { struct listnode* node = list_head(&action_queue); struct action *act = node_to_item(node, struct action, qlist); list_remove(node); return act; } } // 根据action获得包含的第一个command static struct command* get_first_command(struct action* act) { struct listnode* node; node = list_head(&act->commands); if (!node || list_empty(&act->commands)) return NULL; return node_to_item(node, struct command, clist); } // 重新启动那些死去的进程 restart_processes() { process_needs_restart = 0; service_for_each_flags(SVC_RESTARTING, restart_servce_if_needed); } // 这里根据init.rc里面服务service的标志位flag判断如果死亡是否需要重启,最后调用的service_start函数 ~~~
';