位置:首页 > 综合教程 > Linux系统守护进程概念与全流程创建步骤详解

Linux系统守护进程概念与全流程创建步骤详解

时间:2026-06-18  |  作者:318050  |  阅读:0

守护进程是什么? 对许多刚接触 Linux 的朋友来说,这个术语可能有点陌生。简单说,它就是操作系统后台默默运行的一种特殊进程——你平时用的 Web 服务器、数据库、日志系统,背后基本都是它在干活。今天我们就来聊聊守护进程到底是怎么回事,以及如何在 Linux 系统里亲手创建它。

守护进程是什么?linux创建守护进程的步骤详解

一、守护进程是什么?

Linux Daemon(守护进程)是一种运行在后台的特殊进程。它独立于控制终端,周期性执行某种任务,或者等待处理某些发生的事件。不需要用户输入就能运行,并提供某种服务——要么服务于整个系统,要么服务于某个用户程序。

Linux 系统里绝大多数服务器都是通过守护进程实现的。常见的比如系统日志进程 syslogd、Web 服务器 httpd、邮件服务器 sendmail、数据库服务器 mysqld 等等。

守护进程通常在系统启动时开始运行。除非你强行终止,否则它会一直跑到系统关机。由于要使用特殊端口(1-1024)或访问某些特殊资源,它经常以超级用户(root)权限运行。

注意,一个守护进程的父进程是 init 进程——因为它真正的父进程在 fork 出子进程后就已经先退出了,所以它实际上是个由 init 继承的孤儿进程。另外,守护进程是非交互式程序,没有控制终端。因此任何输出(无论是标准输出 stdout 还是标准错误 stderr)都需要特殊处理。

还有一个有趣的小规律:守护进程的名称通常以 d 结尾,比如 sshd、xinetd、crond 等。

二、创建守护进程的步骤

动手之前,先了解几个基本概念:

1. 进程组

每个进程都属于一个进程组。每个进程组有一个进程组号,这个组号等于该进程组组长(组长进程)的 PID。一个进程只能为自己或子进程设置进程组 ID。

2. 会话期

会话期(session)是一个或多个进程组的集合。setsid() 函数用于建立一个新的会话期——如果调用 setsid 的进程不是进程组组长,这个函数会创建一个新的会话期。效果有三:

  • 此进程变成该会话期的首进程
  • 此进程变成一个新进程组的组长进程
  • 此进程没有控制终端(如果之前有,会解除联系)

如果该进程本身已经是进程组组长,调用 setsid 会返回错误。为了保证这一点,我们通常先 fork() 再 exit(),这样只有子进程在运行。

弄懂了这些,就可以按下面步骤来创建守护进程了:

  • (1)在父进程中执行 fork 并 exit 退出
  • (2)在子进程中调用 setsid 函数创建新会话
  • (3)在子进程中调用 chdir 函数,让根目录 "/" 成为子进程的工作目录
  • (4)在子进程中调用 umask 函数,设置进程的 umask 为 0
  • (5)在子进程中关闭任何不需要的文件描述符

下面展开说明每一步的原理:

(1)在后台运行

为避免挂起控制终端,需要将守护进程放入后台执行。做法是在进程中 fork,让父进程终止,让守护进程在子进程中后台运行。

if(pid=fork())
    exit(0); // 父进程结束,子进程继续

(2)脱离控制终端、登录会话和进程组

先说明一下 Linux 中进程与控制终端、登录会话和进程组的关系:

  • 进程属于一个进程组,进程组号(GID)就是进程组长的 PID
  • 一个登录会话可以包含多个进程组,这些进程组共享一个控制终端(通常是创建进程的登录终端)

我们创建守护进程的目的就是摆脱这些继承来的东西。方法就是在第一步的基础上调用 setsid():

setsid();

注意,当进程是会话组长时 setsid() 会调用失败。但第一步已经保证进程不是会话组长了。成功后,进程成为新的会话组长和新的进程组长,与原来的登录会话和进程组彻底脱离。由于会话过程对控制终端是独占的,进程同时也就与控制终端脱离了。

(3)禁止进程重新打开控制终端

此时进程已经是无终端的会话组长,但它仍然可以重新申请打开一个控制终端。为了让进程不再成为会话组长,从而禁止重新打开终端,可以再 fork 一次:

if(pid=fork())
    exit(0); // 结束第一子进程,第二子进程继续(第二子进程不再是会话组长)

(4)关闭打开的文件描述符

进程会从父进程那里继承打开的文件描述符。如果不关闭,会浪费系统资源,甚至导致文件系统无法卸下,或引发不可预料的错误。通常的做法是循环关闭所有可能的文件描述符:

for(i=0; i

(5)改变当前工作目录

进程运行时,其工作目录所在的文件系统不能被卸下。一般需要把工作目录改到根目录。如果需要转储核心、写运行日志,可以改到特定目录如 /tmp:

chdir("/");

(6)重设文件创建掩模

进程从父进程继承文件创建掩模,它可能会影响守护进程创建文件时的存取位。为了消除这种影响,把文件创建掩模清零:

umask(0);

(7)处理 SIGCHLD 信号

这一步不是必须的,但对某些服务器进程来说很重要。当父进程不等待子进程结束时,子进程会成为僵尸进程(zombie),占用系统资源。而如果父进程等待,又会增加负担,影响并发性能。在 Linux 下简单将 SIGCHLD 信号的操作设为 SIG_IGN 即可:

signal(SIGCHLD, SIG_IGN);

这样内核在子进程结束时就不会产生僵尸进程了。需要注意的是,这与 BSD4 不同——后者必须显式等待子进程才能释放僵尸进程。

三、创建守护进程

在动手写代码之前,先确认一下 setsid() 的使用方法:

#include 

以上就是守护进程的基本概念以及 Linux 下创建守护进程的完整步骤。理解这些原理后,在实际项目中搭建稳定的后台服务就会从容得多。

来源:整理自互联网
免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

精选合集

更多

大家都在玩