linux的init进程
一个在线编辑markdown文档的编辑器,是内核启动的第一个进程,init进程有很多重要的任务,它的pit
为1,在linux shell中使用pstree命令可以看到它为其它用户进程的根.以下为某机器的pstree结果。
init─┬─AliHids───9*[{AliHids}]
├─AliYunDun───8*[{AliYunDun}]
├─AliYunDunUpdate───6*[{AliYunDunUpdate}]
├─atd
├─bluetoothd
├─console-kit-dae───64*[{console-kit-dae}]
├─cron
├─dbus-daemon
├─6*[getty]
├─gshelld───3*[{gshelld}]
├─nscd───7*[{nscd}]
├─ntpd
├─polkitd───{polkitd}
├─rsyslogd───3*[{rsyslogd}]
├─sshd─┬─sshd───sftp-server
│ └─sshd───bash───pstree
├─udevd───2*[udevd]
├─upstart-socket-
└─upstart-udev-br
android中的init进程
*android 本身就是基于linux操作系统的,所以两者的init进程是类似的.
init进程的主要工作
首先大概参考下安卓/system/core/ini.c中的目录
int main(int argc, char **argv)
{
int fd_count = 0;
struct pollfd ufds[4];
char *tmpdev;
char* debuggable;
char tmp[32];
int property_set_fd_init = 0;
int signal_fd_init = 0;
int keychord_fd_init = 0;
bool is_charger = false;
if (!strcmp(basename(argv[0]), "ueventd"))
return ueventd_main(argc, argv);
if (!strcmp(basename(argv[0]), "watchdogd"))
return watchdogd_main(argc, argv);
/* clear the umask */
umask(0);
// 下面的代码开始建立各种用户空间的目录,如/dev、/proc、/sys等
mkdir("/dev", 0755);
mkdir("/proc", 0755);
mkdir("/sys", 0755);
mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "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);
/* 检测/dev/.booting文件是否可读写和创建*/
close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000));
open_devnull_stdio();
klog_init();
// 初始化属性
property_init();
get_hardware_name(hardware, &revision);
// 处理内核命令行
process_kernel_cmdline();
… …
is_charger = !strcmp(bootmode, "charger");
INFO("property init
");
if (!is_charger)
property_load_boot_defaults();
INFO("reading config file
");
// 分析/init.rc文件的内容
init_parse_config_file("/init.rc");
… …// 执行初始化文件中的动作
action_for_each_trigger("init", action_add_queue_tail);
// 在charger模式下略过mount文件系统的工作
if (!is_charger) {
action_for_each_trigger("early-fs", action_add_queue_tail);
action_for_each_trigger("fs", action_add_queue_tail);
action_for_each_trigger("post-fs", action_add_queue_tail);
action_for_each_trigger("post-fs-data", action_add_queue_tail);
}
queue_builtin_action(property_service_init_action, "property_service_init");
queue_builtin_action(signal_init_action, "signal_init");
queue_builtin_action(check_startup_action, "check_startup");
if (is_charger) {
action_for_each_trigger("charger", action_add_queue_tail);
} else {
action_for_each_trigger("early-boot", action_add_queue_tail);
action_for_each_trigger("boot", action_add_queue_tail);
}
/* run all property triggers based on current state of the properties */
queue_builtin_action(queue_property_triggers_action, "queue_property_triggers");
#if BOOTCHART
queue_builtin_action(bootchart_init_action, "bootchart_init");
#endif
// 进入无限循环,建立init的子进程(init是所有进程的父进程)
for(;;) {
int nr, i, timeout = -1;
// 执行命令(子进程对应的命令)
execute_one_command();
restart_processes();
if (!property_set_fd_init && get_property_set_fd() > 0) {
ufds[fd_count].fd = get_property_set_fd();
ufds[fd_count].events = POLLIN;
ufds[fd_count].revents = 0;
fd_count++;
property_set_fd_init = 1;
}
if (!signal_fd_init && get_signal_fd() > 0) {
ufds[fd_count].fd = get_signal_fd();
ufds[fd_count].events = POLLIN;
ufds[fd_count].revents = 0;
fd_count++;
signal_fd_init = 1;
}
if (!keychord_fd_init && get_keychord_fd() > 0) {
ufds[fd_count].fd = get_keychord_fd();
ufds[fd_count].events = POLLIN;
ufds[fd_count].revents = 0;
fd_count++;
keychord_fd_init = 1;
}
if (process_needs_restart) {
timeout = (process_needs_restart - gettime()) * 1000;
if (timeout < 0)
timeout = 0;
}
if (!action_queue_empty() || cur_action)
timeout = 0;
// bootchart是一个性能统计工具,用于搜集硬件和系统的信息,并将其写入磁盘,以便其
// 他程序使用
#if BOOTCHART
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;
}
}
#endif
// 等待下一个命令的提交
nr = poll(ufds, fd_count, timeout);
if (nr <= 0)
continue;
for (i = 0; i < fd_count; i++) {
if (ufds[i].revents == POLLIN) {
if (ufds[i].fd == get_property_set_fd())
handle_property_set_fd();
else if (ufds[i].fd == get_keychord_fd())
handle_keychord();
else if (ufds[i].fd == get_signal_fd())
handle_signal();
}
}
}
return 0;
}
- 初始化操作
- 22-24行的创建/dev /proc /sys 目录,具体目录结构可以参考linux目录详解
- 26-31为挂载文件系统
- 51行执行了解析配置文件,然后根据解析结果进行服务的启动。
- 守护服务:84行开始进入守护服务,无限循执行init子进程。
参考链接
感谢以作者文章,排名不分先后