My Practical Experience On Linux

Linux 内核相关

僵尸进程

原因

  • 父进程没有回收子进程的资源
  • 子进程的进程描述符仍然存在,因此子进程成为僵尸进程

解决方法

  • 父进程调用 wait() 函数,回收子进程的资源
  • 或者父进程调用 waitpid() 函数,回收子进程的资源
  • 或者父进程调用 signal(SIGCHLD,SIG_IGN) 函数,忽略 SIGCHLD 信号,让内核自动回收子进程的资源

实际开发

当我们在 Linux 主机上遇到占用显存但是找不到对应的进程时(如下图案例所示),往往就是子进程所占用的资源没有被回收,而父进程已经结束。这种情况一般会在多线程并行当中出现,比如在多线程并行训练模型时,如果主线程在子线程结束之前就已经结束,那么子线程就会变成僵尸进程,占用显存。

僵尸进程案例一 僵尸进程案例二

对应的解决方法,一般可以通过检测僵尸进程,然后再寻找僵尸进程对应的父进程,安全地终止父进程后,操作系统就会自动清理对应的子进程。

  • 检测僵尸进程
    1
    ps aux | grep Z
    在 ps aux 的输出中,僵尸进程(Zombie process)通常会在 STAT(进程状态)列标记为 Z,表示进程已经终止但仍然存在于进程表中,因为其父进程尚未回收它的退出状态。
  1. ps aux

    • ps 命令用于显示当前系统的进程信息,而 aux 选项的作用是:
    • a:显示所有用户的进程(不仅仅是当前用户的)。
    • u:以用户友好的格式(包括用户名、CPU 和内存使用等)显示进程信息。
    • x:显示没有终端控制的进程(例如守护进程)。
      运行 ps aux 会输出系统中所有正在运行的进程的详细信息。
  2. | grep Z

    • |(管道):将 ps aux 命令的输出传递给 grep 进行筛选。
    • grep Z:在 ps aux 的输出中查找包含字母 “Z” 的行。
  • 查找僵尸进程对应的父进程
    1
    ps -o ppid= -p 2721429
    可以通过以上命令,查找僵尸进程对应的父进程的 PID,然后进行终止.
  • 终止父进程
    1
    kill -9 2721429
    当父进程被杀死后,操作系统会自动将这些僵尸进程的父进程设置为 init 进程(PID 1),相当于讲这些僵尸进程转移给了 init 进程作为接管的父进程。init 是系统的主进程,它会自动调用 wait() 来回收所有孤立的僵尸进程,从而清除它们。

nohup 后台运行

原理

nohupno hang up 的缩写,它的作用是让进程在后台运行,即使终端关闭也不会影响进程的运行。

使用方法

1
nohup command > output.log 2>&1 &

其中,command 是要执行的命令,output.log 是输出日志文件,2>&1 表示将标准错误输出重定向到标准输出,& 表示将命令放到后台运行。

实际开发

1
nohup sh test.sh > output.log 2>&1 &

以上一条命令,基本能够解决大多数情况下的后台运行。

My Practical Experience On Linux

https://lzhms.github.io/blog/PracticeOnLinux/

Author

Zhihao Li

Posted on

2024-09-23

Updated on

2025-04-03

Licensed under


Comments