Linux:守护进程(进程组、会话和守护进程)

守护进程(Daemon)是 Linux 系统中一种长期运行的后台进程,通常用于执行系统级别的任务或服务。理解守护进程涉及进程组、会话及其与其他进程的关系。本文将详细介绍这些概念及其在 Linux 中的应用。

一、进程组(Process Group)

进程组是一个或多个进程的集合,用于信号传递和终端输入输出控制。进程组中的每个进程都有一个相同的进程组 ID(PGID),PGID 等于进程组组长的进程 ID(PID)。

1. 创建进程组

当一个进程创建新进程时,默认情况下新进程继承其父进程的 PGID。可以通过调用 setpgid 函数来改变进程的 PGID。

复制代码
#include <unistd.h>
#include <stdio.h>

int main() {
    pid_t pid = fork();

    if (pid == 0) {
        // 子进程
        setpgid(0, 0); // 创建新的进程组
        printf("Child process PGID: %d\n", getpgid(0));
    } else {
        // 父进程
        printf("Parent process PGID: %d\n", getpgid(0));
    }

    return 0;
}
2. 查看进程组

可以使用 ps 命令查看进程的 PGID:

复制代码
ps -o pid,pgid,cmd
二、会话(Session)

会话是一个或多个进程组的集合。会话由一个会话首领进程创建,该进程成为会话的领导者,并且它的 PID 就是会话 ID(SID)。会话首领进程可以通过调用 setsid 函数创建一个新的会话。

1. 创建会话

创建一个新的会话,将当前进程变为会话领导者:

复制代码
#include <unistd.h>
#include <stdio.h>

int main() {
    pid_t sid = setsid(); // 创建新的会话
    if (sid == -1) {
        perror("setsid");
        return 1;
    }
    printf("Session ID: %d\n", sid);
    return 0;
}
2. 查看会话

可以使用 ps 命令查看进程的 SID:

复制代码
ps -o pid,sid,cmd
三、守护进程(Daemon)

守护进程是一种在后台运行的进程,通常由系统启动脚本或其他服务管理工具启动。守护进程脱离控制终端,独立于用户的会话。

1. 创建守护进程

创建守护进程的一般步骤包括:

  1. 创建子进程,终止父进程:确保守护进程不是会话领导者,防止它重新打开控制终端。
  2. 创建新的会话:使守护进程成为新会话的领导者。
  3. 改变工作目录:通常将工作目录更改为根目录,以防止锁定任何挂载的文件系统。
  4. 重设文件权限掩码:防止继承父进程的文件权限。
  5. 关闭文件描述符:关闭继承的文件描述符。

下面是一个创建守护进程的示例代码:

复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>

void daemonize() {
    pid_t pid;

    // 创建子进程
    pid = fork();
    if (pid < 0) {
        exit(EXIT_FAILURE);
    }
    if (pid > 0) {
        exit(EXIT_SUCCESS); // 父进程退出
    }

    // 创建新的会话
    if (setsid() < 0) {
        exit(EXIT_FAILURE);
    }

    // 捕获、忽略 SIGHUP 信号
    signal(SIGHUP, SIG_IGN);

    // 创建新子进程,终止父进程,防止重新获得控制终端
    pid = fork();
    if (pid < 0) {
        exit(EXIT_FAILURE);
    }
    if (pid > 0) {
        exit(EXIT_SUCCESS);
    }

    // 改变工作目录
    if (chdir("/") < 0) {
        exit(EXIT_FAILURE);
    }

    // 重设文件权限掩码
    umask(0);

    // 关闭文件描述符
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);
}

int main() {
    daemonize();

    // 守护进程的主循环
    while (1) {
        // 执行后台任务
        sleep(30); // 示例:每隔30秒执行一次任务
    }

    return EXIT_SUCCESS;
}
四、管理守护进程
1. 使用 systemd

现代 Linux 系统通常使用 systemd 管理守护进程。可以创建一个 systemd 服务文件来管理守护进程。

创建一个示例服务文件 /etc/systemd/system/mydaemon.service

复制代码
[Unit]
Description=My Daemon Service

[Service]
ExecStart=/usr/local/bin/mydaemon
Restart=always
User=nobody
Group=nobody

[Install]
WantedBy=multi-user.target

然后启用并启动服务:

复制代码
sudo systemctl enable mydaemon
sudo systemctl start mydaemon
​
2. 使用 init.d

在旧版 Linux 系统中,可以使用 init.d 脚本管理守护进程。创建一个示例脚本 /etc/init.d/mydaemon

复制代码
#!/bin/sh

### BEGIN INIT INFO
# Provides:          mydaemon
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: My Daemon Service
### END INIT INFO

case "$1" in
    start)
        echo "Starting mydaemon"
        /usr/local/bin/mydaemon &
        ;;
    stop)
        echo "Stopping mydaemon"
        pkill mydaemon
        ;;
    restart)
        $0 stop
        $0 start
        ;;
    *)
        echo "Usage: $0 {start|stop|restart}"
        exit 1
esac

exit 0

然后启用并启动服务:

复制代码
sudo chmod +x /etc/init.d/mydaemon
sudo update-rc.d mydaemon defaults
sudo service mydaemon start
相关推荐
泽虞9 分钟前
《LINUX系统编程》笔记p3
linux·运维·服务器·c语言·笔记·面试
源代码杀手36 分钟前
大模型微调训练资源占用查询:Windows 10 查看 NVIDIA 显卡GPU状态教程(替代 Ubuntu 下 watch nvidia-smi)
linux·windows·ubuntu
苹果醋32 小时前
Java并发编程-Java内存模型(JMM)
java·运维·spring boot·mysql·nginx
dingcb1682 小时前
4090服务器无法sudo apt update 问题解决
运维·服务器
头发那是一根不剩了2 小时前
服务器硬盘进行分区和挂载
linux·运维·服务器
Johny_Zhao2 小时前
Linux防止rm误操作防护方案
linux·网络·人工智能·网络安全·信息安全·云计算·yum源·系统运维
心一信息3 小时前
如何通过华为无线控制器添加一个名为yunwei的无线网络
运维·网络·华为
stark张宇3 小时前
Linux 零基础入门,看这一篇就够了
linux·服务器
TDengine (老段)3 小时前
TDengine IDMP 运维指南(4. 使用 Docker 部署)
运维·数据库·物联网·docker·时序数据库·tdengine·涛思数据
三婶儿3 小时前
在没有客户端的客户环境下,如何用 Python 一键执行 MySQL 与达梦数据库 SQL
运维·后端·python