在前面一篇中,分析了在init的main函数中,会去解析init.rc。那么解析的过程是怎么样的呢?
init.rc的解析函数为:init_parse_config_file.
实现的位置在于:init_parse.c
int init_parse_config_file(const char *fn)
{
char *data;
data = read_file(fn, 0);
if (!data) return -1;
parse_config(fn, data);
DUMP();
return 0;
}
这个函数分为了两个部分:
首先是read_file, 其次是parse_config.
我们先来看看read_file的实现:
150void *read_file(const char *fn, unsigned *_sz)
151{
152 char *data;
153 int sz;
154 int fd;
155 struct stat sb;
156
157 data = 0;
158 fd = open(fn, O_RDONLY); // 打开fn的文件,即打开了init.rc
159 if(fd < 0) return 0; // 如果打开失败,则返回0
160
161 // for security reasons, disallow world-writable
162 // or group-writable files
163 if (fstat(fd, &sb) < 0) { // 得到fd文件描述符所指向文件的文件信息,并填充sb的状态结构体。如果获取失败的话,会返回-1
164 ERROR("fstat failed for '%s'\n", fn);
165 goto oops;
166 }
167 if ((sb.st_mode & (S_IWGRP | S_IWOTH)) != 0) { // 如果其他用户,或者用户组有可以写入这个文件的权限的话,则error
168 ERROR("skipping insecure file '%s'\n", fn);
169 goto oops;
170 }
171
172 sz = lseek(fd, 0, SEEK_END); // 遍历fd文件的长度
173 if(sz < 0) goto oops; // 如果得不到当前的长度的话,返回错误
174
175 if(lseek(fd, 0, SEEK_SET) != 0) goto oops;
176
177 data = (char*) malloc(sz + 2); // malloc一个指针,长度为当前文件长度+2
178 if(data == 0) goto oops; // 如果data没有malloc成功的话,则返回错误。
179
180 if(read(fd, data, sz) != sz) goto oops; //从文件fd中,读取sz的内容,保存到data的数组中
181 close(fd); // 读取完了文件,则要关闭这个文件的描述符
182 data[sz] = '\n';
183 data[sz+1] = 0; //将data给填充,即数组最后为0即EOF
184 if(_sz) *_sz = sz; // if(0), 暂时不考虑
185 return data; // return data
186
187oops:
188 close(fd);
189 if(data != 0) free(data);
190 return 0;
191}
由上面的分析,我们可以得知,在readfile的时候,将init.rc内容全部读取到了data的数组中,并进行了返回。
结合前面的init_parse_file_config可以看到,
data = read_file(fn, 0);
目前的data数组中,保存的就是从文件中读取出来的全部内容。
这个内容就被传入到了parse_config中进行解析。
parse_config(fn, data);
那么parse_config是如何解析的呢?
想要理解这个过程,那我们就要首先看看那init.rc这个文件了。