容器init进程

1号进程

在内核完成了操作系统的各种初始化之后,这个程序需要执行的第一个用户态程就是 init 进程。

目前主流的 Linux 发行版,无论是 RedHat 系的还是 Debian 系的,都会把 /sbin/init 作为符号链接指向 Systemd。Systemd 是目前最流行的 Linux init 进程。

具体在 kernel 里的代码实现如下:

init/main.c

        /*
         * We try each of these until one succeeds.
         *
         * The Bourne shell can be used instead of init if we are
         * trying to recover a really broken machine.
         */

        if (execute_command) {
                ret = run_init_process(execute_command);
                if (!ret)
                        return 0;
                panic("Requested init %s failed (error %d).",
                      execute_command, ret);
        }

        if (!try_to_run_init_process("/sbin/init") ||
            !try_to_run_init_process("/etc/init") ||
            !try_to_run_init_process("/bin/init") ||
            !try_to_run_init_process("/bin/sh"))
                return 0;


        panic("No working init found.  Try passing init= option to kernel. "
              "See Linux Documentation/admin-guide/init.rst for guidance.");
$ ls -l /sbin/init
lrwxrwxrwx 1 root root 20 Feb  5 01:07 /sbin/init -> /lib/systemd/systemd

在 Linux 上有了容器的概念之后,一旦容器建立了自己的 Pid Namespace(进程命名空间),这个 Namespace 里的进程号也是从 1 开始标记的。所以,容器的 init 进程也被称为 1 号进程。

关于这个知识点,你只需要记住: 1 号进程是第一个用户态的进程,由它直接或者间接创建了 Namespace 中的其他进程。

Linux 信号

kill 命令,其实在 Linux 里就是发送一个信号,可以用 kill -l 来看这些信号的编号和名字

$ kill -l
 1) SIGHUP      2) SIGINT    3) SIGQUIT    4) SIGILL    5) SIGTRAP
 6) SIGABRT     7) SIGBUS    8) SIGFPE     9) SIGKILL  10) SIGUSR1
11) SIGSEGV    12) SIGUSR2  13) SIGPIPE   14) SIGALRM  15) SIGTERM
16) SIGSTKFLT  17) SIGCHLD  18) SIGCONT   19) SIGSTOP  20) SIGTSTP
21) SIGTTIN    22) SIGTTOU  23) SIGURG    24) SIGXCPU  25) SIGXFSZ
26) SIGVTALRM  27) SIGPROF  28) SIGWINCH  29) SIGIO    30) SIGPWR
31) SIGSYS

信号(Signal)其实就是 Linux 进程收到的一个通知。

  • 如果我们按下键盘“Ctrl+C”,当前运行的进程就会收到一个信号 SIGINT 而退出;

  • 如果我们的代码写得有问题,导致内存访问出错了,当前的进程就会收到另一个信号 SIGSEGV;

  • 我们也可以通过命令 kill ,直接向一个进程发送一个信号,缺省情况下不指定信号的类型,那么这个信号就是 SIGTERM。也可以指定信号类型,比如命令 "kill -9 ", 这里的 9,就是编号为 9 的信号,SIGKILL 信号。

忽略(Ignore)、捕获(Catch)、缺省行为(Default)

容器init进程_第1张图片

Linux 为每个信号都定义了一个缺省的行为,你可以在 Linux 系统中运行 man 7 signal来查看每个信号的缺省行为。

特权信号SIGKILL 和 SIGSTOP 就是 Linux 为 kernel 和超级用户去删除任意进程所保留的,不能被忽略也不能被捕获。

进程状态中 SigCgt Bitmap

而 C 程序里,缺省状态下,一个信号 handler 都没有注册;bash 程序里注册了两个 handler,bit 2 和 bit 17,也就是 SIGINT 和 SIGCHLD,但是没有注册 SIGTERM。

### golang init
# cat /proc/1/status | grep -i SigCgt
SigCgt:     fffffffe7fc1feff

### C init
# cat /proc/1/status | grep -i SigCgt
SigCgt:     0000000000000000

### bash init
# cat /proc/1/status | grep -i SigCgt
SigCgt:     0000000000010002

重点总结

  1. 第一个概念是 Linux 1 号进程。它是第一个用户态的进程。它直接或者间接创建了 Namespace 中的其他进程。

  1. 第二个概念是 Linux 信号。Linux 有 31 个基本信号,进程在处理大部分信号时有三个选择:忽略、捕获和缺省行为。其中两个特权信号 SIGKILL 和 SIGSTOP 不能被忽略或者捕获。

你可能感兴趣的:(容器技术,linux)