init程序是android啟動後,系統執行的第一個名稱為init的可執行程式。
功能:
裝置管理
解析啟動腳本init.rc
執行啟動腳本中的基本功能
執行啟動腳本中的各種服務
代碼路徑:system/core/init
編譯結果生成一個可執行檔案:init
1.main{}
int main(int argc, char **argv)
{
int device_fd = -1;
int property_set_fd = -1;
int signal_recv_fd = -1;
int keychord_fd = -1;
int fd_count;
int s[2];
int fd;
struct sigaction act;
char tmp[prop_value_max];
struct pollfd ufds[4];
char *tmpdev;
char* debuggable;
act.sa_handler = sigchld_handler;
act.sa_flags = sa_nocldstop;
act.sa_mask = 0;
act.sa_restorer = null;
sigaction(sigchld, &act, 0);
umask(0);
mkdir("/dev", 0755); //建立檔案系統的基本目錄
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);
open_devnull_stdio(); //打開3個檔案:輸入,輸入,錯誤
log_init(); //初始化log
info("reading config file\n");
parse_config_file("/init.rc"); //處理初始化腳本,擷取核心指令行參數
qemu_init();
import_kernel_cmdline(0); //初始化驅動裝置,建立檔案系統節點
get_hardware_name();
snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
parse_config_file(tmp);
action_for_each_trigger("early-init", action_add_queue_tail);
drain_action_queue();
info("device init\n");
device_fd = device_init(); //屬性相關處理和啟動logo
if (emmc_boot){
action_for_each_trigger("emmc", action_add_queue_tail);
drain_action_queue();
}else{
action_for_each_trigger("nand", action_add_queue_tail);
}
property_init();
// only listen for keychords if ro.debuggable is true
keychord_fd = open_keychord();
if (console[0]) {
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);
if( load_565rle_image(init_image_file) ) { //
fd = open("/dev/tty0", o_wronly);
if (fd >= 0) {
const char *msg;
msg = "\n"
"\n"
"\n" // console is 40 cols x 30 lines
" a n d r o i d ";
write(fd, msg, strlen(msg));
close(fd);
if (qemu[0])
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);
property_set("ro.emmc",emmc_boot ? "1" : "0");
action_for_each_trigger("init", action_add_queue_tail);
{
error("pmd processing!\n");
system("/system/bin/pmd");
error("pmd exit!\n");
// }
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);
if ((device_fd < 0) ||
(property_set_fd < 0) ||
(signal_recv_fd < 0)) {
error("init startup failure\n");
return 1;
if (battchg_pause) {
action_for_each_trigger("boot-pause", action_add_queue_tail);
action_for_each_trigger("early-boot", action_add_queue_tail);
action_for_each_trigger("boot", action_add_queue_tail);
queue_all_property_triggers();
property_triggers_enabled = 1;
ufds[0].fd = device_fd; //初始化struct pollfd ufds[4]
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++;
} else {
ufds[3].events = 0;
ufds[3].revents = 0;
#if bootchart
bootchart_count = bootchart_init();
if (bootchart_count < 0) {
error("bootcharting init failure\n");
} else if (bootchart_count > 0) {
notice("bootcharting started (period=%d ms)\n", bootchart_count*bootchart_polling_ms);
notice("bootcharting ignored\n");
#endif
for(;;) { //進入循環,處理ufds[4]的事件
int nr, i, timeout = -1;
for (i = 0; i < fd_count; i++)
ufds[i].revents = 0;
restart_processes();
if (process_needs_restart) {
timeout = (process_needs_restart - gettime()) * 1000;
if (timeout < 0)
timeout = 0;
}
if (bootchart_count > 0) {
if (timeout < 0 || timeout > bootchart_polling_ms)
timeout = bootchart_polling_ms;
if (bootchart_step() < 0 || --bootchart_count == 0) {
bootchart_finish();
bootchart_count = 0;
}
nr = poll(ufds, fd_count, timeout);
if (nr <= 0)
continue;
if (ufds[2].revents == pollin) {
read(signal_recv_fd, tmp, sizeof(tmp));
while (!wait_for_one_process(0))
;
if (ufds[0].revents == pollin)
handle_device_fd(device_fd);
if (ufds[1].revents == pollin)
handle_property_set_fd(property_set_fd);
if (ufds[3].revents == pollin)
handle_keychord(keychord_fd);
return 0;
}