http://blog.youkuaiyun.com/xichangbao/article/details/53024698
一 Init
init进程,它是内核启动的第一个用户级进程。
代码路径system/core/init/
1.0 main
init程序的入口函数是init.cpp中的main函数
int main(int argc, char** argv) {
if (!strcmp(basename(argv[0]), "ueventd")) { // ln -sf ../init /sbin/ueventd
return ueventd_main(argc, argv); // ueventd软链接到了init,当运行ueventd时,执行ueventd_main函数
}
if (!strcmp(basename(argv[0]), "watchdogd")) { // ln -sf ../init /sbin/watchdogd
return watchdogd_main(argc, argv); // watchdogd软链接到了init,当运行watchdogd时,执行watchdogd_main函数
}
// Clear the umask.
umask(0); // 清除umask值
add_environment("PATH", _PATH_DEFPATH); // 设置环境变量PATH=/usr/local/bin:/bin:/usr/bin
bool is_first_stage = (argc == 1) || (strcmp(argv[1], "--second-stage") != 0);
// Get the basic filesystem setup we need put together in the initramdisk
// on / and then we'll let the rc file figure out the rest.
if (is_first_stage) { // 第一次启动init,创建或挂载一些linux根文件系统中的目录
mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
mkdir("/dev/pts", 0755);
mkdir("/dev/socket", 0755);
mount("devpts", "/dev/pts", "devpts", 0, NULL);
#define MAKE_STR(x) __STRING(x)
mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));
mount("sysfs", "/sys", "sysfs", 0, NULL);
mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
}
// We must have some place other than / to create the device nodes for
// kmsg and null, otherwise we won't be able to remount / read-only
// later on. Now that tmpfs is mounted on /dev, we can actually talk
// to the outside world.
open_devnull_stdio(); // init的标准输入,标准输出,标准错误文件描述符定向到/dev/__null__
klog_init(); // 打开/dev/kmsg,init进程的log,打印到内核printk的log buffer
klog_set_level(KLOG_NOTICE_LEVEL); // 设置log级别为5
NOTICE("init %s started!\n", is_first_stage ? "first stage" : "second stage");
if (!is_first_stage) {
// Indicate that booting is in progress to background fw loaders, etc.
close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
property_init(); // 创建/dev/__properties__文件,大小128KB,并映射进内存
// If arguments are passed both on the command line and in DT,
// properties set in DT always have priority over the command-line ones.
process_kernel_dt();
process_kernel_cmdline(); // 解析cmdline中以androidboot.开头的参数,并设置相应的property属性
// Propagate the kernel variables to internal variables
// used by init as well as the current required properties.
export_kernel_boot_props(); 设置"ro.serialno", "ro.bootmode", "ro.baseband", "ro.bootloader","ro.hardware", "ro.revision"的property属性
}
// Set up SELinux, including loading the SELinux policy if we're in the kernel domain.
selinux_initialize(is_first_stage); // 初始化SEAndroid
// If we're in the kernel domain, re-exec init to transition to the init domain now
// that the SELinux policy has been loaded.
if (is_first_stage) {
if (restorecon("/init") == -1) { // 恢复/init的SELinux文件属性
ERROR("restorecon failed: %s\n", strerror(errno));
security_failure();
}
char* path = argv[0];
char* args[] = { path, const_cast<char*>("--second-stage"), nullptr };
if (execv(path, args) == -1) { // execv会停止执行当前的进程,并且以progname应用进程替换被停止执行的进程,进程ID没有改变,这里是运行init,将其从kernel域变成用户域
ERROR("execv(\"%s\") failed: %s\n", path, strerror(errno));
security_failure();
}
}
// These directories were necessarily created before initial policy load
// and therefore need their security context restored to the proper value.
// This must happen before /dev is populated by ueventd.
NOTICE("Running restorecon...\n");
restorecon("/dev"); // 我的看版本restorecon是个空函数?
restorecon("/dev/socket");
restorecon("/dev/__properties__");
restorecon("/property_contexts");
restorecon_recursive("/sys");
epoll_fd = epoll_create1(EPOLL_CLOEXEC); // 表示生成的epoll fd具有“执行后关闭”特性
if (epoll_fd == -1) {
ERROR("epoll_create1 failed: %s\n", strerror(errno));
exit(1);
}
signal_handler_init(); // 子进程退出处理
property_load_boot_defaults(); // 加载/default.prop文件
export_oem_lock_status(); // 设置ro.boot.flash.locked的property属性
start_property_service(); // 启动property属性服务
const BuiltinFunctionMap function_map; // BuiltinFunctionMap:keyword和处理函数
Action::set_function_map(&function_map); // 竟然用到了c++11,表示看不懂
Parser& parser = Parser::GetInstance(); // 单例模式
// init.rc文件基本组成单位是section, section分为三种类型,由三个关键字来区分:on(Action)、service(Service)、import(Import)
parser.AddSectionParser("service",std::make_unique<ServiceParser>()); // Service的parser为ServiceParser // Service section 表示一个可执行程序
parser.AddSectionParser("on", std::make_unique<ActionParser>()); // Action的parser为ActionParser // Action section 表示一系列命令的组合
parser.AddSectionParser("import", std::make_unique<ImportParser>()); // Import的parser为ImportParser // 引入其他rc文件
parser.ParseConfig("/init.rc"); // 开始解析init.rc,这是init的一个核心工作 // init.rc的语法可自行用Google百度一下,网上的资料十分详尽
ActionManager& am = ActionManager::GetInstance(); // 单例模式
am.QueueEventTrigger("early-init"); // 添加early-init EventTrigger // 添加EventTrigger的先后,决定了对应Trigger的执行顺序,early-init是最先执行的
// Queue an action that waits for coldboot done so we know ueventd has set up all of /dev...
am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done"); // 构造并添加action
// ... so that we can start queuing up actions that require stuff from /dev.
am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
am.QueueBuiltinAction(keychord_init_action, "keychord_init");
am.QueueBuiltinAction(console_init_action, "console_init");
// Trigger all the boot actions to get us started.
am.QueueEventTrigger("init"); // 添加init EventTrigger
// Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
// wasn't ready immediately after wait_for_coldboot_done
am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
// Don't mount filesystems or start core system services in charger mode.
std::string bootmode = property_get("ro.bootmode");
if (bootmode == "charger") { // 是否进入关机充电
am.QueueEventTrigger("charger"); // 添加charger EventTrigger
} else {
am.QueueEventTrigger("late-init"); // 正常开机 // 这个Trigger下,主要是完成挂载一些文件系统和启动一些系统service
}
// Run all property triggers based on current state of the properties.
am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");
while (true) {
if (!waiting_for_exec) { // 判断是否有事件需要处理
am.ExecuteOneCommand(); // 执行action中command
restart_processes(); // 重启需要重启的service
}
int timeout = -1;
if (process_needs_restart) { // 有进程需要重启时,将在下面epoll_wait处进行等待
timeout = (process_needs_restart - gettime()) * 1000;
if (timeout < 0)
timeout = 0;
}
if (am.HasMoreCommands()) { // 还有action需要处理,不等待
timeout = 0;
}
bootchart_sample(&timeout); // bootchart是一个性能统计工具
epoll_event ev;
int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, timeout)); // 等待在epoll_fd文件描述符的I/O事件
if (nr == -1) {
ERROR("epoll_wait failed: %s\n", strerror(errno));
} else if (nr == 1) {
((void (*)()) ev.data.ptr)(); // 有事件到来进行处理 // keychord,property设置,signal(例如子进程退出信号)处理
}
}
return 0;
}
1.1 klog_init
void klog_init(void) {
if (klog_fd >= 0) return; /* Already initialized */
klog_fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC); // 打开kmsg文件节点
if (klog_fd >= 0) {
return;
}
static const char* name = "/dev/__kmsg__";
if (mknod(name, S_IFCHR | 0600, (1 << 8) | 11) == 0) {
klog_fd = open(name, O_WRONLY | O_CLOEXEC);
unlink(name);
}
}
1.2 selinux_initialize
static void selinux_initialize(bool in_kernel_domain) {
Timer t;
selinux_callback cb;
cb.func_log = selinux_klog_callback;
selinux_set_callback(SELINUX_CB_LOG, cb); // 将selinux_log的值设置成selinux_klog_callback
cb.func_audit = audit_callback;
selinux_set_callback(SELINUX_CB_AUDIT, cb); // 将selinux_audit的值设置成audit_callback
if (in_kernel_domain) {
INFO("Loading SELinux policy...\n");
if (selinux_android_load_policy() < 0) {
ERROR("failed to load policy: %s\n", strerror(errno));
security_failure();
}
bool kernel_enforcing = (security_getenforce() == 1);
bool is_enforcing = selinux_is_enforcing();
if (kernel_enforcing != is_enforcing) {
if (security_setenforce(is_enforcing)) { // 设置SELinux模式(permissive或enforcing),其实就是写/sys/fs/selinux/enforce文件节点
ERROR("security_setenforce(%s) failed: %s\n",
is_enforcing ? "true" : "false", strerror(errno));
security_failure();
}
}
if (write_file("/sys/fs/selinux/checkreqprot", "0") == -1) { // 1表示SElinux会检查应用请求的保护,0表示默认使用内核对mmap和mprotect系统调用的保护
security_failure();
}
NOTICE("(Initializing SELinux %s took %.2fs.)\n",
is_enforcing ? "enforcing" : "non-enforcing", t.duration());
} else {
selinux_init_all_handles();
}
}
int selinux_android_load_policy(void)
{
int fd = -1, rc;
struct stat sb;
void *map = NULL;
static int load_successful = 0;
/*
* Since updating policy at runtime has been abolished
* we just check whether a policy has been loaded before
* and return if this is the case.
* There is no point in reloading policy.
*/
if (load_successful){
selinux_log(SELINUX_WARNING, "SELinux: Attempted reload of SELinux policy!/n");
return 0;
}
set_selinuxmnt(SELINUXMNT); // 挂载点/sys/fs/selinux
fd = open(sepolicy_file, O_RDONLY | O_NOFOLLOW | O_CLOEXEC); // 打开/sepolicy
if (fd < 0) {
selinux_log(SELINUX_ERROR, "SELinux: Could not open sepolicy: %s\n",
strerror(errno));
return -1;
}
if (fstat(fd, &sb) < 0) {
selinux_log(SELINUX_ERROR, "SELinux: Could not stat %s: %s\n",
sepolicy_file, strerror(errno));
close(fd);
return -1;
}
map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (map == MAP_FAILED) {
selinux_log(SELINUX_ERROR, "SELinux: Could not map %s: %s\n",
sepolicy_file, strerror(errno));
close(fd);
return -1;
}
rc = security_load_policy(map, sb.st_size);
if (rc < 0) {
selinux_log(SELINUX_ERROR, "SELinux: Could not load policy: %s\n",
strerror(errno));
munmap(map, sb.st_size);
close(fd);
return -1;
}
munmap(map, sb.st_size);
close(fd);
selinux_log(SELINUX_INFO, "SELinux: Loaded policy from %s\n", sepolicy_file);
load_successful = 1;
return 0;
}
int security_load_policy(void *data, size_t len)
{
char path[PATH_MAX];
int fd, ret;
if (!selinux_mnt) {
errno = ENOENT;
return -1;
}
snprintf(path, sizeof path, "%s/load", selinux_mnt);
fd = open(path, O_RDWR | O_CLOEXEC); // 打开/sys/fs/selinux/load文件
if (fd < 0)
return -1;
ret = write(fd, data, len); // 将/sepolicy的策略数据写入/sys/fs/selinux/load文件
close(fd);
if (ret < 0)
return -1;
return 0;
}
static void selinux_init_all_handles(void)
{
sehandle = selinux_android_file_context_handle();
selinux_android_set_sehandle(sehandle);
sehandle_prop = selinux_android_prop_context_handle();
}
1.3 signal_handler_init
void signal_handler_init() {
// Create a signalling mechanism for SIGCHLD.
int s[2];
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, s) == -1) { // 建立一对匿名的已经连接的套接字
ERROR("socketpair failed: %s\n", strerror(errno));
exit(1);
}
signal_write_fd = s[0];
signal_read_fd = s[1];
// Write to signal_write_fd if we catch SIGCHLD.
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = SIGCHLD_handler;
act.sa_flags = SA_NOCLDSTOP;
sigaction(SIGCHLD, &act, 0); // Init进程是所有用户空间进程的父进程,需要处理其子进程终止时产生的SIGCHLD信号
ServiceManager::GetInstance().ReapAnyOutstandingChildren();
register_epoll_handler(signal_read_fd, handle_signal); // 注册epoll handler,当signal_read_fd有数据可读时,调用handle_signal
}
static void SIGCHLD_handler(int) {
if (TEMP_FAILURE_RETRY(write(signal_write_fd, "1", 1)) == -1) { // 当子进程退出时,向signal_write_fd写1
ERROR("write(signal_write_fd) failed: %s\n", strerror(errno));
}
}
void register_epoll_handler(int fd, void (*fn)()) {
epoll_event ev;
ev.events = EPOLLIN;
ev.data.ptr = reinterpret_cast<void*>(fn);
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) {
ERROR("epoll_ctl failed: %s\n", strerror(errno));
}
}
static void handle_signal() {
// Clear outstanding requests.
char buf[32];
read(signal_read_fd, buf, sizeof(buf));
ServiceManager::GetInstance().ReapAnyOutstandingChildren();
}
1.4 ReapAnyOutstandingChildren
void ServiceManager::ReapAnyOutstandingChildren() {
while (ReapOneProcess()) {
}
}
bool ServiceManager::ReapOneProcess() {
int status;
pid_t pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG)); // 等待子进程退出,WNOHANG表示非阻塞
if (pid == 0) {
return false;
} else if (pid == -1) {
ERROR("waitpid failed: %s\n", strerror(errno));
return false;
}
Service* svc = FindServiceByPid(pid); // 根据pid查找到相应的Service
std::string name;
if (svc) {
name = android::base::StringPrintf("Service '%s' (pid %d)",
svc->name().c_str(), pid);
} else {
name = android::base::StringPrintf("Untracked pid %d", pid);
}
if (WIFEXITED(status)) { // WIFEXITED(status)如果子进程正常结束则为非0值。
NOTICE("%s exited with status %d\n", name.c_str(), WEXITSTATUS(status)); // WEXITSTATUS(status)取得子进程exit()返回的结束代码
} else if (WIFSIGNALED(status)) { // WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真。
NOTICE("%s killed by signal %d\n", name.c_str(), WTERMSIG(status)); // WTERMSIG(status)取得子进程因信号而中止的信号代码
} else if (WIFSTOPPED(status)) { // WIFSTOPPED(status)如果子进程处于暂停执行情况则此宏值为真。
NOTICE("%s stopped by signal %d\n", name.c_str(), WSTOPSIG(status)); // WSTOPSIG(status)取得引发子进程暂停的信号代码
} else {
NOTICE("%s state changed", name.c_str());
}
if (!svc) {
return true;
}
if (svc->Reap()) { // 结束服务
waiting_for_exec = false;
RemoveService(*svc); // 移除服务
}
return true;
}
bool Service::Reap() {
if (!(flags_ & SVC_ONESHOT) || (flags_ & SVC_RESTART)) { // 当flags为RESTART,且不是ONESHOT时
NOTICE("Service '%s' (pid %d) killing any children in process group\n",
name_.c_str(), pid_);
kill(-pid_, SIGKILL); // 杀死以pid_为组标识的进程
}
// Remove any sockets we may have created.
for (const auto& si : sockets_) { // 移除当前服务svc创建的所有socket
std::string tmp = StringPrintf(ANDROID_SOCKET_DIR "/%s", si.name.c_str());
unlink(tmp.c_str());
}
if (flags_ & SVC_EXEC) { // 当flags为EXEC时
INFO("SVC_EXEC pid %d finished...\n", pid_);
return true;
}
pid_ = 0;
flags_ &= (~SVC_RUNNING);
// Oneshot processes go into the disabled state on exit,
// except when manually restarted.
if ((flags_ & SVC_ONESHOT) && !(flags_ & SVC_RESTART)) {
flags_ |= SVC_DISABLED;
}
// Disabled and reset processes do not get restarted automatically.
if (flags_ & (SVC_DISABLED | SVC_RESET)) { // 当flag为ONESHOT时,将其设为stopped状态
NotifyStateChange("stopped");
return false;
}
time_t now = gettime();
if ((flags_ & SVC_CRITICAL) && !(flags_ & SVC_RESTART)) {
if (time_crashed_ + CRITICAL_CRASH_WINDOW >= now) { // 服务在4分钟内重启次数超过4次,则重启手机进入recovery模式
if (++nr_crashed_ > CRITICAL_CRASH_THRESHOLD) {
ERROR("critical process '%s' exited %d times in %d minutes; "
"rebooting into recovery mode\n", name_.c_str(),
CRITICAL_CRASH_THRESHOLD, CRITICAL_CRASH_WINDOW / 60);
android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
return false;
}
} else {
time_crashed_ = now;
nr_crashed_ = 1;
}
}
flags_ &= (~SVC_RESTART);
flags_ |= SVC_RESTARTING;
// Execute all onrestart commands for this service.
onrestart_.ExecuteAllCommands(); // 执行当前service中所有onrestart命令,不得不说Android代码越来越复杂了,这一块代码原来是很简洁的,现在写得都快看不懂了,汗
NotifyStateChange("restarting"); // 将service设为restarting状态
return false;
}
1.5 start_property_service
void start_property_service() {
property_set_fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, // 创建socket并绑定到/dev/socket/property_service
0666, 0, 0, NULL);
if (property_set_fd == -1) {
ERROR("start_property_service socket creation failed: %s\n", strerror(errno));
exit(1);
}
listen(property_set_fd, 8); // 监听这个socket,当客户端调用connect()发出连接请求,服务器端就会收到这个请求。
register_epoll_handler(property_set_fd, handle_property_set_fd);
}
int create_socket(const char *name, int type, mode_t perm, uid_t uid,
gid_t gid, const char *socketcon)
{
struct sockaddr_un addr;
int fd, ret, savederrno;
char *filecon;
if (socketcon) {
if (setsockcreatecon(socketcon) == -1) {
ERROR("setsockcreatecon(\"%s\") failed: %s\n", socketcon, strerror(errno));
return -1;
}
}
fd = socket(PF_UNIX, type, 0);
if (fd < 0) {
ERROR("Failed to open socket '%s': %s\n", name, strerror(errno));
return -1;
}
if (socketcon)
setsockcreatecon(NULL);
memset(&addr, 0 , sizeof(addr));
addr.sun_family = AF_UNIX;
snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s",
name);
ret = unlink(addr.sun_path);
if (ret != 0 && errno != ENOENT) {
ERROR("Failed to unlink old socket '%s': %s\n", name, strerror(errno));
goto out_close;
}
filecon = NULL;
if (sehandle) {
ret = selabel_lookup(sehandle, &filecon, addr.sun_path, S_IFSOCK);
if (ret == 0)
setfscreatecon(filecon);
}
ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr));
savederrno = errno;
setfscreatecon(NULL);
freecon(filecon);
if (ret) {
ERROR("Failed to bind socket '%s': %s\n", name, strerror(savederrno));
goto out_unlink;
}
ret = lchown(addr.sun_path, uid, gid);
if (ret) {
ERROR("Failed to lchown socket '%s': %s\n", addr.sun_path, strerror(errno));
goto out_unlink;
}
ret = fchmodat(AT_FDCWD, addr.sun_path, perm, AT_SYMLINK_NOFOLLOW);
if (ret) {
ERROR("Failed to fchmodat socket '%s': %s\n", addr.sun_path, strerror(errno));
goto out_unlink;
}
INFO("Created socket '%s' with mode '%o', user '%d', group '%d'\n",
addr.sun_path, perm, uid, gid);
return fd;
out_unlink:
unlink(addr.sun_path);
out_close:
close(fd);
return -1;
}
// 服务器端依次调用socket()、bind()、listen()建立,绑定,监听指定的socket地址;TCP客户端依次调用socket()、connect()创建,连接向TCP服务器发送连接请求;服务器监听到请求之后,调用accept()函数接收请求,至此服务器端和客户端连接建立完成。
static void handle_property_set_fd()
{
prop_msg msg;
int s;
int r;
struct ucred cr;
struct sockaddr_un addr;
socklen_t addr_size = sizeof(addr);
socklen_t cr_size = sizeof(cr);
char * source_ctx = NULL;
struct pollfd ufds[1];
const int timeout_ms = 2 * 1000; /* Default 2 sec timeout for caller to send property. */
int nr;
if ((s = accept(property_set_fd, (struct sockaddr *) &addr, &addr_size)) < 0) { // 建立连接
return;
}
/* Check socket options here */
if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {
close(s);
ERROR("Unable to receive socket options\n");
return;
}
ufds[0].fd = s;
ufds[0].events = POLLIN;
ufds[0].revents = 0;
nr = TEMP_FAILURE_RETRY(poll(ufds, 1, timeout_ms)); // 监测连接
if (nr == 0) {
ERROR("sys_prop: timeout waiting for uid=%d to send property message.\n", cr.uid);
close(s);
return;
} else if (nr < 0) {
ERROR("sys_prop: error waiting for uid=%d to send property message: %s\n", cr.uid, strerror(errno));
close(s);
return;
}
r = TEMP_FAILURE_RETRY(recv(s, &msg, sizeof(msg), MSG_DONTWAIT)); // 读取数据
if(r != sizeof(prop_msg)) {
ERROR("sys_prop: mis-match msg size received: %d expected: %zu: %s\n",
r, sizeof(prop_msg), strerror(errno));
close(s);
return;
}
switch(msg.cmd) {
case PROP_MSG_SETPROP:
msg.name[PROP_NAME_MAX-1] = 0;
msg.value[PROP_VALUE_MAX-1] = 0;
if (!is_legal_property_name(msg.name, strlen(msg.name))) {
ERROR("sys_prop: illegal property name. Got: \"%s\"\n", msg.name);
close(s);
return;
}
getpeercon(s, &source_ctx);
if(memcmp(msg.name,"ctl.",4) == 0) {
// Keep the old close-socket-early behavior when handling
// ctl.* properties.
close(s);
if (check_control_mac_perms(msg.value, source_ctx, &cr)) {
handle_control_message((char*) msg.name + 4, (char*) msg.value); // 运行,停止,重启service
} else {
ERROR("sys_prop: Unable to %s service ctl [%s] uid:%d gid:%d pid:%d\n",
msg.name + 4, msg.value, cr.uid, cr.gid, cr.pid);
}
} else {
if (check_mac_perms(msg.name, source_ctx, &cr)) {
property_set((char*) msg.name, (char*) msg.value); // 设置property
} else {
ERROR("sys_prop: permission denied uid:%d name:%s\n",
cr.uid, msg.name);
}
// Note: bionic's property client code assumes that the
// property server will not close the socket until *AFTER*
// the property is written to memory.
close(s);
}
freecon(source_ctx);
break;
default:
close(s);
break;
}
}
1.6 Action Command
BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
static const Map builtin_functions = {
{"bootchart_init", {0, 0, do_bootchart_init}},
{"chmod", {2, 2, do_chmod}},
{"chown", {2, 3, do_chown}},
{"class_reset", {1, 1, do_class_reset}},
{"class_start", {1, 1, do_class_start}},
{"class_stop", {1, 1, do_class_stop}},
{"copy", {2, 2, do_copy}},
{"domainname", {1, 1, do_domainname}},
{"enable", {1, 1, do_enable}},
{"exec", {1, kMax, do_exec}},
{"export", {2, 2, do_export}},
{"hostname", {1, 1, do_hostname}},
{"ifup", {1, 1, do_ifup}},
{"insmod", {1, kMax, do_insmod}},
{"installkey", {1, 1, do_installkey}},
{"load_persist_props", {0, 0, do_load_persist_props}},
{"load_system_props", {0, 0, do_load_system_props}},
{"loglevel", {1, 1, do_loglevel}},
{"mkdir", {1, 4, do_mkdir}},
{"mount_all", {1, kMax, do_mount_all}},
{"mount", {3, kMax, do_mount}},
{"powerctl", {1, 1, do_powerctl}},
{"restart", {1, 1, do_restart}},
{"restorecon", {1, kMax, do_restorecon}},
{"restorecon_recursive", {1, kMax, do_restorecon_recursive}},
{"rm", {1, 1, do_rm}},
{"rmdir", {1, 1, do_rmdir}},
{"setprop", {2, 2, do_setprop}},
{"setrlimit", {3, 3, do_setrlimit}},
{"setusercryptopolicies", {1, 1, do_setusercryptopolicies}},
{"start", {1, 1, do_start}},
{"stop", {1, 1, do_stop}},
{"swapon_all", {1, 1, do_swapon_all}},
{"symlink", {2, 2, do_symlink}},
{"sysclktz", {1, 1, do_sysclktz}},
{"trigger", {1, 1, do_trigger}},
{"verity_load_state", {0, 0, do_verity_load_state}},
{"verity_update_state", {0, 0, do_verity_update_state}},
{"wait", {1, 2, do_wait}},
{"write", {2, 2, do_write}},
};
return builtin_functions;
}
1.7 ParseConfig
这是一个很好的解析配置文件的实现。
bool Parser::ParseConfig(const std::string& path) {
if (is_dir(path.c_str())) {
return ParseConfigDir(path);
}
return ParseConfigFile(path);
}
bool Parser::ParseConfigFile(const std::string& path) {
INFO("Parsing file %s...\n", path.c_str());
Timer t;
std::string data;
if (!read_file(path.c_str(), &data)) {
return false;
}
data.push_back('\n'); // TODO: fix parse_config.
ParseData(path, data); // 解析init.rc的内容
for (const auto& sp : section_parsers_) {
sp.second->EndFile(path);
}
// Turning this on and letting the INFO logging be discarded adds 0.2s to
// Nexus 9 boot time, so it's disabled by default.
if (false) DumpState(); // 打印Service和Action的状态信息
NOTICE("(Parsing %s took %.2fs.)\n", path.c_str(), t.duration());
return true;
}
void Parser::ParseData(const std::string& filename, const std::string& data) {
//TODO: Use a parser with const input and remove this copy
std::vector<char> data_copy(data.begin(), data.end());
data_copy.push_back('\0');
parse_state state;
state.filename = filename.c_str();
state.line = 0;
state.ptr = &data_copy[0];
state.nexttoken = 0;
SectionParser* section_parser = nullptr;
std::vector<std::string> args;
for (;;) {
switch (next_token(&state)) { // 以行为单位分割init.rc中的数据
case T_EOF: // 文件结束
if (section_parser) {
section_parser->EndSection();
}
return;
case T_NEWLINE: // 换行符
state.line++;
if (args.empty()) {
break;
}
if (section_parsers_.count(args[0])) { // 判断是否为一个新的Section,在init.rc中以on、sevice、import关键字开头
if (section_parser) {
section_parser->EndSection();
}
section_parser = section_parsers_[args[0]].get(); // 获取关键字对应的parser
std::string ret_err;
if (!section_parser->ParseSection(args, &ret_err)) { // 调用parser的ParseSection函数
parse_error(&state, "%s\n", ret_err.c_str());
section_parser = nullptr;
}
} else if (section_parser) { // 不是一个新的section,而是Service section的option或者Action section中的command
std::string ret_err;
if (!section_parser->ParseLineSection(args, state.filename, // 调用parser的ParseLineSection函数
state.line, &ret_err)) {
parse_error(&state, "%s\n", ret_err.c_str());
}
}
args.clear();
break;
case T_TEXT: // 文本内容添加到vector
args.emplace_back(state.text);
break;
}
}
}
1.8 Service Option
Service::OptionHandlerMap::Map& Service::OptionHandlerMap::map() const {
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
static const Map option_handlers = {
{"class", {1, 1, &Service::HandleClass}},
{"console", {0, 1, &Service::HandleConsole}},
{"critical", {0, 0, &Service::HandleCritical}},
{"disabled", {0, 0, &Service::HandleDisabled}},
{"group", {1, NR_SVC_SUPP_GIDS + 1, &Service::HandleGroup}},
{"ioprio", {2, 2, &Service::HandleIoprio}},
{"keycodes", {1, kMax, &Service::HandleKeycodes}},
{"oneshot", {0, 0, &Service::HandleOneshot}},
{"onrestart", {1, kMax, &Service::HandleOnrestart}},
{"seclabel", {1, 1, &Service::HandleSeclabel}},
{"setenv", {2, 2, &Service::HandleSetenv}},
{"socket", {3, 6, &Service::HandleSocket}},
{"user", {1, 1, &Service::HandleUser}},
{"writepid", {1, kMax, &Service::HandleWritepid}},
};
return option_handlers;
}
1.9 ExecuteOneCommand
按照Trigger队列的顺序,一次只执行一个action中的一个command
void ActionManager::ExecuteOneCommand() {
// Loop through the trigger queue until we have an action to execute
while (current_executing_actions_.empty() && !trigger_queue_.empty()) { // 遍历Trigger队列,找到第一个action不为的Trigger
for (const auto& action : actions_) { // 遍历action向量
if (trigger_queue_.front()->CheckTriggers(*action)) { // 当Action的Trigger与Trigger队列的队首元素相同,将其添加到当前需要执行的队列中
current_executing_actions_.emplace(action.get());
}
}
trigger_queue_.pop(); // 已处理的Trigger出队
}
if (current_executing_actions_.empty()) {
return;
}
auto action = current_executing_actions_.front(); // 每次只执行一个action
if (current_command_ == 0) {
std::string trigger_name = action->BuildTriggersString();
INFO("processing action (%s)\n", trigger_name.c_str());
}
action->ExecuteOneCommand(current_command_); // 执行Action的一个command
// If this was the last command in the current action, then remove
// the action from the executing list.
// If this action was oneshot, then also remove it from actions_.
++current_command_;
if (current_command_ == action->NumCommands()) { // 判断当前正在执行中command是其action中的最后一个command
current_executing_actions_.pop(); // action出队
current_command_ = 0;
if (action->oneshot()) { // oneshot action不会再次执行,将其从action向量中删除
auto eraser = [&action] (std::unique_ptr<Action>& a) {
return a.get() == action;
};
actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser));
}
}
}