Linux任务管理与守护进程

Linux任务管理与守护进程


Linux任务管理与守护进程详解

任务管理

进程组概念

在Linux中,每个进程不仅有进程ID(PID),还属于一个进程组。进程组是一个或多个进程的集合,通常与同一作业相关联,可接收同一终端的信号。

  • 进程组ID(PGID):每个进程组有唯一标识。
  • 组长进程:其PGID等于PID,可创建组内进程并终止。
  • 存在性:只要组内有一个进程存在,进程组就存在,与组长进程是否终止无关。

作业概念

Shell通过**作业(Job)进程组(Process Group)**管理前后台任务,而非直接控制单个进程。

  • 作业组成:一个作业可包含多个进程。
  • 作业控制:Shell支持一个前台作业和多个后台作业。
  • 作业与进程组的区别:若作业中的进程创建子进程,该子进程不属于作业。作业结束后,若子进程仍存在,会自动变为后台进程组。

会话概念

**会话(Session)**是一个或多个进程组的集合,通常与一个控制终端关联(如终端设备或伪终端)。

  • 控制进程:会话首进程与终端建立连接。
  • 进程组划分:会话包含一个前台进程组和多个后台进程组。
  • 示例 :运行5个死循环程序:
    • mytest1 & mytest2 &:后台进程组。
    • mytest3 | mytest4 | mytest5:前台进程组。
    • Shell单独成组,共享同一会话和控制终端。
  • 信号传递 :终端输入(如 Ctrl+C 生成 SIGINT)只发送给前台进程组。

相关操作

前台进程&后台进程
  • 前台运行./program,状态为 R+(带+表示前台)。
  • 后台运行./program &,状态为 R,输出类似 [1] 16437,其中 [1] 是作业编号,16437 是进程ID。
  • 多进程示例:启动4个后台进程,分别标记为1-4号作业。
jobs、fg、bg
  • jobs:查看当前会话的作业列表。
  • fg :将作业提到前台。
    • 示例:fg 1,将1号作业提至前台,状态变为 R+
    • 注意:前台只能有一个进程,bash会自动变为后台。
  • bg :让停止的作业在后台继续运行。
    • 示例:Ctrl+Z 停止前台进程(状态变为 T),bg 1 恢复运行(状态为 R)。
    • 本质:发送 SIGCONT 信号。
ps命令查看指定的选项
  • ps -o:自定义输出字段,查看当前会话进程信息。
  • 会话关系:登录创建bash进程,形成一个会话,所有命令行任务共享同一会话ID(SESS)。
  • 系统级查看ps axj,显示所有进程。

守护进程

守护进程的概念

**守护进程(Daemon)**是一种运行在后台的特殊进程,独立于控制终端,周期性执行任务或等待事件。

  • 特点:无控制终端,不受用户登录注销影响。
  • 实例inetd(Internet服务器)、httpd(Web服务器)、crond(作业调度)。
  • 命名 :通常以 d 结尾,如 syslogd

守护进程的查看

使用 ps axj 查看:

  • 参数
    • a:列出所有用户进程。
    • x:包括无终端进程。
    • j:显示作业控制信息。
  • 标识 :TPGID为 -1 表示无控制终端,即守护进程。
  • 内核线程 :COMMAND以 [ ] 括起来,通常以 k 开头(如 [kthreadd])。

常见守护进程

  • udevd:管理 /dev 设备文件。
  • acpid:电源管理。
  • syslogd:日志维护。

守护进程的创建

原生创建守护进程

创建步骤:

  1. 设置文件掩码umask(0),确保文件权限符合预期。
  2. 创建新会话fork() 后父进程退出,子进程调用 setsid() 与终端脱离。
  3. 忽略SIGCHLDsignal(SIGCHLD, SIG_IGN),避免僵尸进程。
  4. 再次fork(可选):确保子进程不是会话首进程,防止重新关联终端。
  5. 更改目录(可选)chdir("/"),便于绝对路径访问资源。
  6. 重定向IO(可选) :将标准输入/输出/错误重定向至 /dev/null

代码示例

c 复制代码
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
    umask(0);
    if (fork() > 0) exit(0);
    setsid();
    signal(SIGCHLD, SIG_IGN);
    if (fork() > 0) exit(0);
    chdir("/");
    close(0);
    int fd = open("/dev/null", O_RDWR);
    dup2(fd, 1);
    dup2(fd, 2);
    while (1);
    return 0;
}

验证

  • ps axj:TPGID为 -1,TTY为 ?
  • PID ≠ PGID ≠ SID,非组长且独立会话。
  • /proc/<pid>:工作目录为 /,IO重定向至 /dev/null
调用daemon函数创建守护进程
c 复制代码
int daemon(int nochdir, int noclose);
  • 参数
    • nochdir:0时更改目录为 /
    • noclose:0时重定向IO至 /dev/null
  • 示例
c 复制代码
#include <unistd.h>
int main() {
    daemon(0, 0);
    while (1);
    return 0;
}

特点:创建的守护进程是会话首进程(SID=PID),未防止终端关联。

模拟实现daemon函数

自定义实现:

c 复制代码
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
void my_daemon(int nochdir, int noclose) {
    umask(0);
    if (fork() > 0) exit(0);
    setsid();
    signal(SIGCHLD, SIG_IGN);
    if (fork() > 0) exit(0);
    if (!nochdir) chdir("/");
    if (!noclose) {
        close(0);
        int fd = open("/dev/null", O_RDWR);
        dup2(fd, 1);
        dup2(fd, 2);
    }
}
int main() {
    my_daemon(0, 0);
    while (1);
    return 0;
}

优势 :比系统 daemon 多一步 fork,更彻底脱离终端。


总结

  • 任务管理 :通过进程组、作业和会话实现前后台控制,jobsfgbg 等命令提供灵活操作。
  • 守护进程 :后台运行的特殊进程,创建需脱离终端,可通过原生步骤或 daemon 函数实现。
相关推荐
柯一梦25 分钟前
Linux权限以及常用热键集合
linux
UNbuff_01 小时前
Linux ip 命令使用指南
linux·网络·tcp/ip
努力努力再努力wz1 小时前
【C++进阶系列】:万字详解红黑树(附模拟实现的源码)
java·linux·运维·c语言·开发语言·c++
会飞的土拨鼠呀1 小时前
Linux负载如何判断服务器的压力
linux·服务器·php
zhongwenhua5201 小时前
tina linux新增mpp程序
linux·mpp·v853
白鹭1 小时前
apache详细讲解(apache介绍+apache配置实验+apache实现https网站)
linux·运维·apache·apache配置·apache实现https网站
被遗忘的旋律.2 小时前
Linux驱动开发笔记(十)——中断
linux·驱动开发·笔记
凡间客3 小时前
Linux防火墙-Firewalld
linux·运维·服务器
nnerddboy3 小时前
Linux嵌入式自学笔记(基于野火EBF6ULL):1.配置环境
linux·笔记·单片机·嵌入式硬件
Justin_193 小时前
Linux防火墙firewalld
大数据·linux·运维