公众号【嵌入式er笔记】持续记录和分享C/C++、Linux、ARM、Android、IoT等技术相关知识,以及职场、生活经验和感悟。
分类: 嵌入式
2013-08-16 20:44:41
原文地址:【转】kernel起来后android之init详解 作者:sh365
转自:http://blog.csdn.net/fu_shuwu/article/details/6017403
Linux kernel起来后运行的第一个应用程序就是init,
Init属于linux下一个应用程序,其源码在 system/core/init中,main是应用程序的入口。从main()函数就可以知道init主要功能。
(1)安装SIGCHLD信号。(如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie)从而占用系统资源。因此需要对SIGCHLD信号做出处理,回收僵尸进程的资源,避免造成不必要的资源浪费。 act.sa_flags = SA_NOCLDSTOP; act.sa_mask = 0; act.sa_restorer = NULL; sigaction(SIGCHLD, &act, 0);
(2)为rootfs建立必要的文件夹,并挂载适当的分区。 mkdir("/proc", 0755); mkdir("/sys", 0755); mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755"); mkdir("/dev/pts", 0755); mkdir("/dev/socket", 0755); mount("devpts", "/dev/pts", "devpts", 0, NULL); mount("proc", "/proc", "proc", 0, NULL); mount("sysfs", "/sys", "sysfs", 0, NULL); (3)创建/dev/null和/dev/kmsg节点。 open_devnull_stdio(); log_init();
(4)解析/init.rc,将所有服务和操作信息加入链表。
(5)从/proc/cmdline中提取信息内核启动参数,并保存到全局变量。 qemu_init();
import_kernel_cmdline(0);
parse_config_file(tmp);
drain_action_queue(); device_init(); {int fd; fd = open_uevent_socket(); if(fd < 0) return -1; fcntl(fd, F_SETFD, FD_CLOEXEC); fcntl(fd, F_SETFL, O_NONBLOCK); coldboot(fd, "/sys/class"); coldboot(fd, "/sys/block"); coldboot(fd, "/sys/devices"); return fd; }
debuggable = property_get("ro.debuggable"); if (debuggable && !strcmp(debuggable, "1")) keychord_fd = open_keychord();
(12)打开console,如果cmdline中没有指定console,则打开却省的/dev/console。 snprintf(tmp, sizeof(tmp), "/dev/%s", console); console_name = strdup(tmp); } fd = open(console_name, O_RDWR); if (fd >= 0) have_console = 1;
close(fd); fd = open("/dev/tty0", O_WRONLY); if (fd >= 0) { const char *msg; msg = "/n" "/n" A N D R O I D "; write(fd, msg, strlen(msg)); close(fd); }
} import_kernel_cmdline(1); if (!strcmp(bootmode,"factory")) property_set("ro.factorytest", "1"); else if (!strcmp(bootmode,"factory2")) property_set("ro.factorytest", "2"); else property_set("ro.factorytest", "0"); property_set("ro.serialno", serialno[0] ? serialno : ""); property_set("ro.bootmode", bootmode[0] ? bootmode : "unknown"); property_set("ro.baseband", baseband[0] ? baseband : "unknown"); property_set("ro.carrier", carrier[0] ? carrier : "unknown"); property_set("ro.bootloader", bootloader[0] ? bootloader : "unknown"); property_set("ro.hardware", hardware); snprintf(tmp, PROP_VALUE_MAX, "%d", revision);
property_set("ro.revision", tmp); action_for_each_trigger("init", action_add_queue_tail);
drain_action_queue(); /* read any property files on system or data and * fire up the property service. This must happen * after the ro.foo properties are set above so * that /data/local.prop cannot interfere with them. */
property_set_fd = start_property_service(); if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0) { signal_fd = s[0]; signal_recv_fd = s[1]; fcntl(s[0], F_SETFD, FD_CLOEXEC); fcntl(s[0], F_SETFL, O_NONBLOCK); fcntl(s[1], F_SETFD, FD_CLOEXEC); fcntl(s[1], F_SETFL, O_NONBLOCK);
} action_for_each_trigger("early-boot", action_add_queue_tail); action_for_each_trigger("boot", action_add_queue_tail);
drain_action_queue(); queue_all_property_triggers();
drain_action_queue(); ufds[0].events = POLLIN; ufds[1].fd = property_set_fd; ufds[1].events = POLLIN; ufds[2].fd = signal_recv_fd; ufds[2].events = POLLIN; fd_count = 3; if (keychord_fd > 0) { ufds[3].fd = keychord_fd; ufds[3].events = POLLIN; fd_count++; }
在这个循环体内,将通过poll模式POLLIN来监视device/property-set/chid-process-exit等事件, |
比如,SD卡插入时,init中device_fd将能收到卡插入事件,以便可以创建节点。 另外,所有其他的重要进程都是init的子进程,一旦这些子进程出现意外,init的signal_recv_fd将收到SIGCHLD,系统将可以做后续处理。
|