这一期呢,我们主要是学习我们的init进程脚本如何解析我们的启动脚本的,我们init进程做完一些初始化的工作之后就会解析我们的启动脚本,他的启动过程主要分为下面几个部分
第一个就是使用init_parse_config_file函数来解析我们的启动脚本,把我们的启动脚本的每一个命令全部解析到我们的一个列表中; 第二个就会调用 action_for_each_trigger和queue_builtin_action这两个函数把我们所解析的相关的操作加到我们的action_queue的队列中,然后就会从action队列中取相应的操作创建相关的服务或执行相关的命令,最后再去守护我们相关的服务那么我们首先来看一下我们解析脚本的一个过程
首先我们会调用init_parse_config_file来解析我们的init.rc ,在解析前,我们首先打开我们的init.rc ,然后调用parse_config这个函数来解析我们的启动脚本,在解析过程中主要涉及到以下几个数据结构和链表 我们的数据结构包括:import_list和struct listnode import_list主要是用来保存我们init.rc中所导入的其他脚本文件,比如init.u***.rc等 struct listnode主要是用来保存启动脚本中所有的操作命令 而我们的三个链表呢,是用来保存我们命令的这三个链表分别是:service_list 、action_list 、action_queue service_list主要是用来保存我们脚本中所有的服务 action_list 主要是用来保存我们所有的操作 action_queue主要是执行的链表 我们解析完的服务和相关的操作全都放在service_list和action_list这两个链表中,然后我们会使用其他的方法,把我们的在初始化过程中需要执行的服务和命令添加到我们的action_queue链表中,最后由我们的init进程根据action_queue中服务和命令来执行相关的操作,我们代开代码来看一下init_parse_config_file函数
他首先会打开我们这个文件,然后调用parse_config这个函数来解析这个文件,这个解析文件就是一个简单的语法解析器
在这里会有一个parse_state变量,我们后边在看,我们再看他解析过程中,首先就是调用我们的next_token ,next_token就是一个语句中的最小单元,我们再看一下我们的启动脚本
我们一个最小的单元就是指:on 、early-init 、write 、、proc/1/oom_adj 、-16 他们都是独立的单元,下面我们来看一下我们的next_token,
他一共有三个返回值,第一个是T_EOF,也就是我们的文件解析完成,完成之后就走到了我们的parser_done
他在这里就会把我们的import_list列表中所包含的其他的init脚本,在这里重新做解析,这就是在解析完之后他会导入其他的脚本 那我们的第二个返回值是T_NEWLINE,他在执行的过程中会首先看一下我们的关键字,也就是我们返回的第一个args,如果说第一个args是SECTION的话,那么他就会调用state.parse_line做一个解析,然后调用parse_new_section这个函数,稍后我们会看到这两个函数的意思 我们再来看一下第三个返回值,他是T_TEXT,他在这里就相当于我们命令中的一个参数。 下面我们来看一下我们next_token的一个具体实现
他的解析过程是根据我们这里的变量parse_state来决定的,这里的parse_state有一个nexttoken ,这个nexttoken保存着我们解析的一个状态,如果说我们在上一次解析中把这个nexttoken给设置了,那么我们会首先执行上次所设置的状态,在这个状态中会直接返回,然后把这个状态直接清0,交给我们的parse_config,而我们没有设置这个状态呢,我们就会真正的去解析这个脚本
他解析的过程呢是一个字符一个字符的去判断,如果我们遇到的是0,那么我们就认为这个文件解析完成,返回一个T_EOF,如果我们遇到一个“n”,那么就说明我们遇到了一个新的一行,这时就会返回一个T_NEWLINE,如果我们遇到其他字符可以继续操作,如果说我们遇到一个#号,这个是一个注释行,我们可以把它忽略,然后返回一个新的行。 其实从第一个for循环我们可以看到,我们这个for循环的作用就是把我们脚本中没用的字符,比如说n 、t 、以及无用的空格等给清除掉,过滤掉,因为我们调用一次肯定是上次遇到了一个完整的单词,或者说遇到了一个完整的行,进来之后呢,他里边第一个必须遇到一个正常的字母,然后才能说明他有一个新的token,这是我们第一个for循环的作用。如果我们在for循环最后遇到一个字符,就会调到我们的text标签中执行,下面我们来看一下我们的text
在这里主要是解析我们最小的一个token,如果说我们上一个遇到了一个字符,那么他在这里就会解析这个单词的结束,如果下一个是0的话,他在这里就会走一下textdone ,如果我们遇到的是空格、n 、 t 、r我们就说我们遇到了一个完整的单词 ,这个单词就会返回,如果遇到n ,我们可以看到我们在这里设置了nexttoken,是T_NEWLINE,然后在这里也走到了textdone,如果我们遇到了一个引号,那么它就会去做一些相关的事情,接下来来我们来看一下我们的textdone
在这里textdone他就是标记了这个字符的一个级数位置,然后返回了一个T_TEXT,也就是返回了一个完整的单词,这就是我开门nexttoken所做的一个操作,了解了nexttoken之后呢,我们就知道了解析的一个最小的元素是如何来生成的,然后我们会根据返回值做一些不同的操作,如果说我们返回的是一个T_NEWLINE,那么我们就可以查找一下我们下一行是一个什么样的语法,下面我们来看一下lookup_keyword的实现,我们将下面的内容放到下一期来学习。
|