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 函数实现。
相关推荐
卷卷的小趴菜学编程10 分钟前
Linux系统之----基础IO
linux·运维·服务器·文件·fopen·文件操作符·位图传递标志位
陈苏同学1 小时前
[已解决] VS Code / Cursor / Trae 的 PowerShell 终端 conda activate 进不去环境的常见问题
linux·windows·conda
我不是秃头sheep1 小时前
Ubuntu 安装 Docker(镜像加速)完整教程
linux·ubuntu·docker
靡樊1 小时前
网络基础概念
linux·服务器·网络·c++·学习
Kusunoki_D2 小时前
速查 Linux 常用指令 II
linux·运维·服务器
xmweisi022 小时前
Ansible内置模块之 group
linux·运维·ansible·rhce·rhca·红帽认证
小猪写代码2 小时前
Ubuntu 系统默认已安装 python,此处只需添加一个超链接即可
linux·python·ubuntu
孤寂大仙v3 小时前
【Linux笔记】——Linux线程理解与分页存储的奥秘
linux·运维·笔记
有谁看见我的剑了?4 小时前
ubuntu 22.04 wifi网卡配置地址上网
linux·运维·ubuntu
码农新猿类4 小时前
Ubuntu摄像头打开失败
linux·运维·ubuntu