牛骨文教育服务平台(让学习变的简单)

源码位置:/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
");
        } else {
            int ret = init_parse_config_file(args[1]);
            if (ret)
                ERROR("could not import file %s
", 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函数