当前位置:首页 > 系统教程 > 正文

Linux进程间关系与守护进程(从入门到实践)

Linux进程间关系与守护进程(从入门到实践)

在Linux系统中,进程是资源分配的基本单位,理解Linux进程间的关系以及守护进程的运作机制,是系统编程和运维的基础。本文将以通俗易懂的方式,带你掌握这些核心概念,并深入探讨进程关系Linux进程管理技巧。

一、进程基础概念

进程是程序的一次执行实例,每个进程都有唯一的PID(进程ID)。通过pstop命令可以查看系统中运行的进程。在Linux中,除了init进程(PID=1)外,其他进程都由其父进程创建。

二、进程间关系

2.1 父子进程

通过fork()系统调用,父进程可以创建子进程。子进程继承父进程的资源,但拥有独立的地址空间。可以使用getppid()获取父进程ID。

2.2 孤儿进程与僵尸进程

当父进程先于子进程退出时,子进程成为孤儿进程,会被init进程收养。如果子进程退出而父进程未调用wait(),子进程的残留信息(如PID)会保留,形成僵尸进程,占用系统资源。

2.3 进程组与会话

每个进程属于一个进程组,进程组ID(PGID)等于组长进程的PID。多个进程组构成一个会话,会话首进程通常是登录shell。理解进程关系有助于管理作业和控制终端。

Linux进程间关系与守护进程(从入门到实践) Linux进程 守护进程 进程关系 Linux进程管理 第1张

三、守护进程详解

3.1 什么是守护进程

守护进程(Daemon)是在后台运行、不受终端控制的特殊进程,通常以字母“d”结尾(如sshd、httpd)。它们执行系统服务,在系统启动时启动,直到系统关闭。

3.2 守护进程的特点

  • 后台运行,没有控制终端
  • 生命周期较长,通常随系统启动和终止
  • 以root或其他专用用户身份运行
  • 工作目录通常为/,避免影响文件系统
  • 文件权限掩码(umask)通常设为0

3.3 创建守护进程的步骤

  1. fork()创建子进程,父进程退出(确保子进程不是组长进程)
  2. 子进程调用setsid()创建新会话,脱离控制终端
  3. 再次fork()并让父进程退出(确保不会重新获得终端)
  4. 改变工作目录到/chdir("/")
  5. 重设文件权限掩码umask(0)
  6. 关闭所有打开的文件描述符
  7. 将标准输入、输出、错误重定向到/dev/null

3.4 实例:用C语言创建一个简单守护进程

    #include #include #include #include #include #include int main() {    pid_t pid = fork();    if (pid < 0) exit(EXIT_FAILURE);    if (pid > 0) exit(EXIT_SUCCESS);  // 父进程退出    // 子进程成为会话首进程    if (setsid() < 0) exit(EXIT_FAILURE);    // 第二次fork    pid = fork();    if (pid < 0) exit(EXIT_FAILURE);    if (pid > 0) exit(EXIT_SUCCESS);    // 更改工作目录    chdir("/");    // 重设文件权限掩码    umask(0);    // 关闭所有文件描述符    for (int x = sysconf(_SC_OPEN_MAX); x >= 0; x--) close(x);    // 重定向标准流到/dev/null    open("/dev/null", O_RDWR);  // stdin    dup2(0, 1);  // stdout    dup2(0, 2);  // stderr    // 守护进程主循环    while(1) {        // 执行任务...        sleep(30);    }    return 0;}  

通过以上步骤,我们创建了一个真正的守护进程,它独立于终端运行,适用于各种系统服务。

四、总结

本文详细介绍了Linux进程间的父子关系、孤儿/僵尸进程、进程组与会话,以及守护进程的原理和创建方法。掌握这些进程关系Linux进程管理技能,能够帮助你更好地理解系统行为,编写健壮的后台程序。希望这篇教程对你有帮助!