你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

关于Linux里养僵尸的事情

[复制链接]
gaosmile 发布时间:2020-7-14 12:14
Linux里养僵尸是怎么回事呢?Linux相信大家都很熟悉,但是Linux里养僵尸是怎么回事呢,下面就让小编带大家一起了解吧。

- 1 -

在终端下启动一个命令,如果在命令结束前关掉终端,它还能正常运行吗?




- 2 -

这其实是一个很常见的case,但凡 Linux 或者 Mac 用得多一点,都会遇到。

在我还是一个穷酸学生的2009年,每个月都需要支付 20 元巨款(当时能买3根鸭脖),通过一个禁止分享网络的认证客户端接入校园网。

为了共建和谐宿舍 节省网费,我历经千辛万苦,交叉编译开源的Linux认证客户端,集成到固件里,并刷到了我的 NETGEAR 路由器上。

然后山水 BBS 的 Linux 版主把我的帖子置顶了 11 年。可见他有多痛恨禁止共享网络。

这么一回忆,感觉自己的共享经济思维真是前卫,当时怎么就没想到去搞共享单车呢?

微信图片_20200714120559.jpg

扯远了,在捣腾的过程中,我就踩了这么个坑:当我ssh到路由器上、刚启动认证时,能够正常联网;但是退出ssh后一会,网就断了。

经过一番捣腾后发现,只要一退出ssh,认证程序就凉了,而不是继续在后台保持和认证服务器的通信。



- 3 -

所以前面那个问题,我以为大部分候选人应该会回答“否”,但没想到竟然还有不少人回答“是”。

其实回答“是”也没什么错,因为确实也有些命令不会随着终端关闭而结束。

问题是当我追问当时执行的是什么命令时,候选人往往又说不出个所以然来。

微信图片_20200714120602.jpg
(借学长的表情一用)

然后我就感到很强的挫败感:这不按剧本来,没法问了啊……只好换题。

当然大部分候选人确实被坑过,于是我可以接着问:

如果确实需要在后台继续执行命令怎么办呢?

有些人只记得要在后面加个 & ;但也有不少人知道前面还得加个 nohup,就像这样:

  1. $ nohup python process.py &
  2. [1] 1806824
  3. nohup: ignoring input and appending output to 'nohup.out'
复制代码

注:其实我更喜欢 screen(或 tmux),偶尔也用 setsid。

然后就可以放心地关闭终端 开始放羊 了。

但我的套题还没结束:为什么加上 nohup 就可以让进程在后台继续运行呢?

微信图片_20200714120605.png
(这表情熟悉吗)



- 4 -

铺垫了这么多,总算是可以开始填坑了。

答案其实很好找,man nohup 就能看到:
The nohup utility invokes utility with its arguments and at this time sets the signal SIGHUP to be ignored
nohup工具在启动命令的同时会将 SIGHUP 信号设置为忽略。

而关于 SIGHUP,Wikipedia原文是这样介绍的:
On POSIX-compliant platforms, SIGHUP ("signal hang up") is a signal sent to a process when its controlling terminal is closed.
wikipedia.org/wiki/SIGHUP
对于 POSIX 兼容的平台(如Unix、Linux、BSD、Mac),当进程所在的控制终端关闭时,系统会给进程发送 SIGHUP 信号(Signal Hang Up,挂断信号)。

为什么叫 SIGHUP 呢?(严正申明:这一问不在套题里)

我们知道,在上古时代,捉 bug 就已经是码农的必备技能(更准确地说是 moth)。

微信图片_20200714120609.jpg
(我总觉得这个图是假的)

到了远古时代,他们不再需要去机房,通过基于 RS-232 协议的串行线路连接到大型机的终端上,就可以开始收福报。

收完福报,程序员通知自己的猫(modem)挂断(Hang Up)连接;大型机的 OS 检测到连接断开,就会给进程发送信号 —— 所以这信号被称为 SIGHUP 。

这果然是毫无卵用的知识啊。

微信图片_20200714120613.jpg



- 5 -

很多同学在操作系统的课程上学习了“进程间的通信方式有信号、管道、消息队列、共享内存……”,但是对信号到底是个什么东西,并没有现实的概念。

课堂教学的理论和实践往往是割裂的,在此特别推荐《Unix环境高级编程》(简称APUE)。

广告
UNIX环境高级编程 第3版
作者:[美]W.,理查德·史蒂文斯(W.,Richard,Stevens)史蒂芬·A.,拉戈(,Stephen,A.,Rago)
京东






APUE在 1.9 - 信号 中写到:信号是通知进程已发生某种条件的一种技术。

而在 Linux/Unix 下,进程对信号的处理有三种选择:
  • 按系统默认方式处理
  • 提供一个回调函数
  • 或忽略该信号(有些信号例外,不允许被忽略)


以 SIGHUP 信号为例,系统默认处理方式就是结束进程

当然终端下打开的第一个进程通常都是shell(例如bash)。shell会给 SIGHUP 信号注册一个回调函数,用于给该 shell 下所有的子进程发送 SIGHUP 信号,然后再主动退出。

对于求生欲很强的程序(例如nohup),可以主动选择忽略该信号

微信图片_20200714120615.png

有一些进程本来就被设计成在后台运行,不需要控制终端,因此它们将 SIGHUP 挪作它用,一个常见的用法就是重新读取配置文件(例如Apache、Nginx),logrotate 正是利用了这一点。

终于填完了坑。



- 6 -

说了这么多都还是纸上谈兵,实操中如何主动忽略 SIGHUP 呢?

实际上也很简单,使用 Linux 的 signal 系统调用即可:

  1. #include <signal.h>
  2. #include <unistd.h>

  3. int main() {
  4.     signal(SIGHUP, SIG_IGN);
  5.     sleep(1000);
  6.     return 0;
  7. }
复制代码

不妨试试看,编译运行起来,即使关闭终端,它也会在后台继续运行。

signal 也可以用于指定回调函数(或重置为系统默认处理方式),这里就不展开了,感兴趣的同学可以参考 APUE 里的代码,以及阅读 signal 的manual。

广告
UNIX环境高级编程 第3版
作者:[美]W.,理查德·史蒂文斯(W.,Richard,Stevens)史蒂芬·A.,拉戈(,Stephen,A.,Rago)
京东






使用回调函数还需要注意一个坑:

由于回调函数可能在任意时刻被触发,因此要避免调用不可重入的函数(典型如printf)。常见的做法是 set 一个 flag,然后在程序的主循环中检测该 flag,再按需执行相应任务。



- 7 -

SIGHUP 只是常见的一个信号,在 Linux 下,信号还有大量其他的场景和应用。

当你按下 Ctrl + C ,就是给进程发送了一个 SIGINT 信号。

当你执行 kill -9 $PID,就是给进程发送了一个 SIGKILL 信号。可能和你期望有出入的是,SIGKILL 是不可以被进程忽略的。所以有时候你得用 SIGTERM。

你还可以使用可自定义的 SIGUSR1、SIGUSR2、SIGURG 来实现一些功能,比如《踩坑记#2:Go服务锁死》中提到 Golang 在其 goroutine 调度中使用了 SIGURG 。



- 8 -

这次就不总结了,最后再用一个和信号有关的 case 收尾。

Linux 内核会为每一个进程分配一个 task_struct 结构体,用于保存进程的相关信息。

在进程死亡后,系统会发送一个 SIGCHLD 信号给它的父进程。

正确的父进程实现,通常应当使用 wait 系统调用来给子进程收尸 —— 父进程往往需要知道子进程结束这个事件,而且可能还需要得知其退出原因(exit code)。

然后内核才会将对应的 task_struct 释放。

如果父进程没有收尸,task_struct 里的 state 会一直保持为 EXIT_ZOMBIE,这时在 ps 或 top 等命令里,就可以看到该进程的状态为 Z ,而且无法被 kill 。

这就是所谓的僵尸进程,这时候你找九叔都没用。

微信图片_20200714120618.jpg
(大半夜找这图还挺渗人的)

所以Linux里养僵尸,其实就是子进程死了父进程不收尸,大家可能会很惊讶Linux里怎么会养僵尸呢?但事实就是这样,小编也感到非常惊讶。

这就是关于Linux里养僵尸的事情了,大家有什么想法呢,欢迎在评论区告诉小编一起讨论哦!

收藏 评论0 发布时间:2020-7-14 12:14

举报

0个回答

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版