1.init启动过程
linux内核启动–>用户空间中启动init进程–>启动其他系统进程–>init变成守护进程
内核空间:–>start_kernel
–>rest_init :kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
–>kernel_init
–>run_init_process(execute_command)
用户空间:–>init进程
–>启动用户空间其他进程
2.处理子进程终止
分析init.c源代码:
位置:Z:\项目\system\core\init
int main(int argc, char **argv)
{
...
queue_builtin_action(signal_init_action, "signal_init"); //跳转2.1解析
...
//init进程的事件处理循环
for(;;) {
...
/*当有signal_recv_fd的时候,注册struct pollfd结构体,监听的文件描述符为signal_recv_fd,监听的事件为POLLIN*/
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;
}
...
//开始监听
nr = poll(ufds, fd_count, timeout);
if (nr <= 0)
continue;
//某个文件套接字有动静进行分析处理
for (i = 0; i < fd_count; i++) {
if (ufds[i].revents & POLLIN) {//判断是哪一个套接字发生了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;
}
2.1
queue_builtin_action(int (*func)(int nargs,char **args), char *name)
是以name形成action,挂在action_list上;以func和name组成command,挂在action的commands上。然后加入到action_queue的队尾。
之后执行signal_init_action–>signal_init
static int signal_fd = -1; //子进程套接字
static int signal_recv_fd = -1; //init进程套接字
static void sigchld_handler(int s)
{
write(signal_fd, &s, 1); //往signal_fd的文件中写1,signal_recv_fd会发现
}
void signal_init(void)
{
int s[2];//套接字的两个fd
//注册SIGCHLD信号,当发生SIGCHLD信号时候调用sigchld_handler函数
struct sigaction act;
memset(&act, 0, sizeof(act));
//sigchld_handler函数是往文件描述符为 signal_fd的套接字写1
act.sa_handler = sigchld_handler;
act.sa_flags = SA_NOCLDSTOP;
sigaction(SIGCHLD, &act, 0);
/* 创建一对已经连接的通信套接字signal_fd和signal_recv_fd,当发生SIGCHLD信号的时候,sigchld_handle函数把signal_fd设置为1,此时通过套接字对,signal_recv_fd也被设置为1。main函数中的poll会监视signal_recv_fd的值,当发现为1的时候,init进程就会调用handle_signal() */
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是设置文件描述符属性的函数
fcntl(s[0], F_SETFL, O_NONBLOCK);
fcntl(s[1], F_SETFD, FD_CLOEXEC);
fcntl(s[1], F_SETFL, O_NONBLOCK);
}
handle_signal(); //不明白handle_signal()出现在这
}
分析handle_signal见init进程_处理子进程终止2
学习辛苦啦,现在不妨换换思路,瞧点文学东西,
如果你喜欢,聊历史,思哲学,品诗集,赏国学。
那就关注公众号:二校五叔
这个是博主的文学公众号啦^ _ ^