守护进程和后台进程的理解

守护进程是一种独立于终端并在后台运行的进程,通常由init进程管理。创建守护进程涉及fork()和setsid()函数,以确保进程与终端和会话独立。通过两次fork()调用,防止成为会话首进程,确保稳定运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于守护进程和后台进程, 一直以为是一个东西。然而并不是。

概念

先看下 chatGPT上对二者的描述:在这里插入图片描述
在这里插入图片描述

如何创建守护进程

通常情况下,守护进程的父进程是init进程(PID为1)。在类Unix系统中,init进程是系统引导过程的第一个进程,是所有其他进程的祖先进程。

当一个守护进程启动时,它会创建一个子进程并终止自己,使得子进程成为新的守护进程。这样的设计是为了确保守护进程不会成为孤儿进程(没有父进程),并且能够继续在系统中运行。

由于init进程是系统中的根进程,它会接收并处理孤儿进程。当守护进程的父进程终止时(通常是init进程接收到子进程的终止信号),init进程会接管并处理守护进程的状态和资源释放。

因此,init进程通常是守护进程的父进程,负责维护和管理守护进程的生命周期。

代码示例:

	/* Daemonizing */
	pid = fork();
	if (pid < 0) {
		DEBUG_MSG("fork error");
		exit(1);
	}
	else if (pid > 0) {
		DEBUG_MSG("parent exits");
		exit(0);
	}

	/* Process Independency */
	if (setsid() < 0) {
		DEBUG_MSG("setsid error");
		exit(1);
	}

	/* Fork again, daemon process is re-parented to init(PID 1) */
	pid = fork();
	if (pid < 0) {
		DEBUG_MSG("fork error");
		exit(1);
	}
	else if (pid > 0) {
		DEBUG_MSG("parent exits");
		exit(0);
	}

这段代码展示了创建守护进程的过程。工作原理如下:

1.pid = fork();:通过调用fork()函数创建一个子进程。子进程的pid为0,父进程的pid为子进程的进程ID。

2.检查pid的值,如果pid小于0,则表示fork()调用失败,输出错误消息并退出程序。

3.如果pid大于0,说明当前代码在父进程中执行。父进程通过输出调试消息表明自己正在退出,并调用exit(0)来正常终止进程。

4.setsid():子进程调用setsid()函数创建一个新的会话,并成为该会话的首进程。这使得子进程独立于其父进程和终端会话。

5.检查setsid()的返回值,如果小于0,则表示出现错误,输出错误消息并退出程序。

6.pid = fork();:子进程再次调用fork()函数创建一个新的子进程。这样做是为了确保守护进程不会成为会话首进程(因为会话首进程无法终止)。

7.检查pid的值,如果pid小于0,则表示fork()调用失败,输出错误消息并退出程序。

8.如果pid大于0,说明当前代码在第二次fork后的子进程中执行。子进程通过输出调试消息表明自己正在退出,并调用exit(0)来正常终止进程。

最终,执行这段代码的进程将会变成一个守护进程。这个守护进程与终端会话分离,成为一个独立的进程,并且它的父进程是init进程(PID为1)。

会话、终端、进程之间的关系

会话(Session)、终端(Terminal)和进程(Process)之间有以下关系:

  1. 会话:会话是一个抽象的概念,代表一个用户与系统进行交互的时间段。它可以包含多个终端会话和相关联的进程。一个会话通常从用户登录开始,直到用户注销或系统关闭。每个会话都有一个唯一的会话ID(Session ID)。
  2. 终端:终端是用户与计算机系统进行交互的设备或应用程序。在传统的计算机系统中,终端通常是指物理终端设备,如计算机控制台、终端机或虚拟终端。在现代的操作系统中,终端也可以是指终端仿真器(Terminal Emulator)软件,如命令行终端、终端窗口或终端模拟器。一个终端可以关联一个会话。
  3. 进程:进程是正在执行的程序的实例。它是操作系统中进行资源分配和管理的基本单位。每个进程都有一个唯一的进程ID(Process ID),用于标识和管理进程。一个进程可以关联一个终端会话。

关系描述:

  • 一个会话可以包含多个终端会话。例如,用户在登录后可能同时在多个终端上进行交互,这些终端会话都属于同一个会话。
  • 一个终端会话通常关联一个终端设备或终端仿真器,它是用户与系统进行交互的接口。
  • 一个终端会话可以关联一个或多个进程。这些进程可以是用户启动的应用程序、命令行工具或其他进程。
  • 一个进程可以属于一个终端会话,从而与一个终端关联。这意味着进程可以通过关联的终端接收输入和发送输出。
    总结来说,会话是用户与系统交互的时间段,终端是用户与系统交互的接口,而进程是正在执行的程序实例,可以与终端会话关联起来以接收输入和发送输出。

为什么要这样创建守护进程

守护进程的设计目标是在后台长期运行,独立于任何终端会话。

守护进程通常不会成为会话的首进程。当一个进程成为会话的首进程时,它会自动拥有控制终端。这意味着它能够接收来自终端的输入和发送输出到终端。但对于守护进程来说,与终端相关的交互是不必要的,而且可能会引起一些问题,例如无法完全脱离终端,或者因为接收到来自终端的信号而终止运行。

为了确保守护进程的独立性和稳定性,常见的做法是采用以下步骤:

1.调用setsid()函数:它会创建一个新的会话并使调用进程成为该会话的首进程。这样,守护进程就不再与原始终端会话相关联。
2. 第二次调用fork():通过再次调用fork(),创建一个新的子进程。这样做是为了确保守护进程不会成为会话的首进程,因为会话首进程无法终止。

通过这种方式,守护进程将成为新会话的成员,但不会成为会话的首进程。它将与终端完全分离,不再受终端会话的影响。这有助于确保守护进程能够在后台长期运行,并且不会因为与终端相关的问题而受到干扰。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值