容器学习(一):进程

前言

​ 最近感觉自己对于容器这块的理解好像仅限于 docker 相关的使用,因此想深入的了解学习一下关于容器的东西,还有就是想借学习容器的时候进一步了解一下 Linux,今天先来简单记录一下容器进程侧相关的笔记。

​ 学习内容源自:极客时间容器实战高手课

容器进程

init 进程

​ 通俗的来说就是 linux 启动之后第一个启动的用户态进程,也就是 pid 1,随便看一台 Linux 上都能够看到 pid 1 的进程

这里可以看到 init 是一个软连接指向 systemd,Linux 的其他进程都是由它创建出来的

image-20221231103924480

那么回过头来看容器,一旦容器建立了自己的 Pid Namespace(进程命名空间),这个 Namespace 里的进程号也是从 1 开始标记的。所以,容器的 init 进程也被称为 1 号进程。

image-20221231153619902

课程中从 kill pid 1 进程的结果展开讨论,说实话我之前完全没考虑过这个问题

比如说下面,我希望让 jupyter notebook 重启,那么我之前都是直接 kill 1 ,但是并没有了解后续的逻辑比如为什么 kill -9 不行但是 kill 可以,因为在我的理解中 kill -9 应该是更加彻底才对

image-20221231153754894

所以针对这个问题需要学习一下 Linux 中关于进程和信号的一些东西

信号

在平时使用的时候我们经常会用到 kill -9 pid ,这里的 9 其实就是信号,我们可以通过 kill -l 来列出所有信号

image-20221231155137489

信号可以理解为进程收到的通知,进程有不同的状态,当进程收到信号之后进程会根据收到的信号来做出对应的状态转换(也有可能不做状态转换)

在文中主要介绍的两个信号就是 SIGTERM(15)和 SIGKILL(9)这两个信号,对应的其实就是 kill pid 和 kill -9 pid,SIGTERM这个信号就是 Linux kill 命令缺省 (default) 发出的

上面说过当进程收到信号之后会做一些状态的转换,我这边理解为的是状态机,主要是下面三个选择

  1. 忽略(ignore):就是对这个信号不做任何处理,但是有两个信号例外,对于 SIGKILL 和 SIGSTOP (这个信号同样也是用于进程停滞的)这个两个信号,进程是不能忽略的。这是因为它们的主要作用是为 Linux kernel 和超级用户提供删除任意进程的特权。
  2. 捕获(catch):这个是指让用户进程可以注册自己针对这个信号的 handler,同样针对 SIGKILL 和 SIGSTOP 信号也是不能添加 handler 的,即不能有自己的处理代码
  3. 缺省(default):默认值,比如 kill pid 这里的缺省值就是 SIGTERM

所以这里回到开头,我们的 kill -9 1 其实就是对 pid 为 1 的进程发了一个 SIGKILL,kill 1 就是对 pid 为 1 的进程发了一个 SIGTERM,至于进程对这两者的信号有不同的响应就需要继续看了,因为上面我们提过 SIGKILL 信号对于进程来说是不能忽略的那么正常情况下 pid 1 的进程应该是要接受到信号并且退出的,但是却没有

所以需要去看一下 Linux 内核中是如何处理的

在 Linux 中执行 kill 命令,其实是调用了内核函数 sys_kill(),而内核在决定把信号发送给 1 号进程的时候,会调用 sig_task_ignored() 这个函数来做个判断,它会决定内核在哪些情况下会把发送的这个信号给忽略掉。如果信号被忽略了,那么 init 进程就不能收到指令了。

image-20221231163000662

这里和我们本文相关的主要是第二个 if 判断,可以看到有三个条件,只有三个条件都满足了才不会将信号发送给进程

image-20221231170544940

  1. !(force && sig_kernel_only(sig)) 如果在同一 namespace 下那么 force 为 0 亿以及 & 关系所以为 true

  2. handler == SIG_DFL SIG_DFL 是系统的缺省 handler,这个缺省的 handler 就叫作 SIG_DFL,由于 SIGKILL 是不能被捕获的,所以就是默认的 handler

    对于 SIGTERM 来说,只要用户不注册 handler 那么这个条件也是成立

  3. t->signal->flags & SIGNAL_UNKILLABLE 代表进程必须为 SIGNAL_UNKILLABLE 标签 ,文中说到只要 pid 为 1 就会有这个标签

kernel/fork.c
                       if (is_child_reaper(pid)) {
                                ns_of_pid(pid)->child_reaper = p;
                                p->signal->flags |= SIGNAL_UNKILLABLE;
                        }

static inline bool is_child_reaper(struct pid *pid)
{
        return pid->numbers[pid->level].nr == 1;
}

所以如果我们要 kill init 进程的话有几个办法

  1. 不同namespace ,宿主机 kill 容器 pid (不现实,生产环境往往没有宿主机权限)
  2. 给进程注册 handler 同样不现实

我们可以通过 cat /proc/1/status | grep SigCgt 来查看是否注册 handler , 如果结果为 0000000000000000 那么就说明是默认缺省 handler 我们是可以 kill 的

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇