几种进程

孤儿进程,僵尸进程,守护进程

孤儿进程概念

我们经常听别人说到孤儿进程(Orphan Process),究竟是什么呢,现在我们一次理解透。

根据维基百科的解释,孤儿进程指的是在其父进程执行完成或被终止后仍继续运行的一类进程。

孤儿进程与僵尸进程是完全不同的,后面会详细介绍僵尸进程。而孤儿进程借用了现实中孤儿的概念,也就是父进程不在了,子进程还在运行,这时我们就把子进程的PPID设为1。前面讲PID提到,操作系统会创建进程号为1的init进程,它没有父进程也不会退出,可以收养系统的孤儿进程。

作用

在现实中用户可能刻意使进程成为孤儿进程,这样就可以让它与父进程会话脱钩,成为后面会介绍的守护进程。

僵尸进程

当一个进程完成它的工作终止之后,它的父进程需要调用wait()或者waitpid()系统调用取得子进程的终止状态。

一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。

理解了孤儿进程和僵尸进程,我们临时加了守护进程这一小节,守护进程就是后台进程吗?没那么简单。

守护(Daemon)进程

我们可以认为守护进程就是后台服务进程,因为它会有一个很长的生命周期提供服务,关闭终端不会影响服务,也就是说可以忽略某些信号。

实现守护进程

首先要保证进程在后台运行,可以在启动程序后面加&,当然更原始的方法是进程自己fork然后结束父进程。

if (pid=fork()) {
  exit(0); // Parent process
}

然后是与终端、进程组、会话(Session)分离。每个进程创建时都绑定一个终端,而且属于一个进程组(进程组也有GID不过等同进程组长的PID),这些进程组在一个会话中,如果是子进程一般会从父进程继承这些信息,想要与环境分离可以使用以下的系统调用。

setsid();

同样地我们会从父进程继承文件掩码(mask),可以手动清理掩码。

umask(0);

如果需要我们可以改变当前工作目录,避免运行时必须使用当前所在的文件系统。

使用Nohup

前面提到过Nohup命令,是让程序以守护进程运行的方式之一,程序运行后忽略SIGHUP信号,也就说关闭终端不会影响进程的运行。类似的命令还有disown,这里不再详述。

下一节:进程的概念大家都很熟悉,但你是否能准确说出僵尸进程的含义呢?还有COW(Copy On Write)、Flock(File Lock)、Epoll和Namespace的概念又是否了解过呢?