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. 忽略SIGCHLD :signal(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,更彻底脱离终端。


总结

  • 任务管理 :通过进程组、作业和会话实现前后台控制,jobs、fg、bg 等命令提供灵活操作。
  • 守护进程 :后台运行的特殊进程,创建需脱离终端,可通过原生步骤或 daemon 函数实现。
相关推荐
木卫二号Coding3 小时前
推荐Linux统计文件大小并操作删除工具-ncdu
linux·运维·服务器
zhangrelay4 小时前
机械臂末端规划智能模型的误区演示
linux·笔记·学习·ubuntu·ros2
Ivanqhz6 小时前
正余弦位置编码(Sinusoidal Positional Encoding)
java·linux·数据库
H.莓飛6 小时前
【数据结构】队列
linux·数据结构·centos
小此方7 小时前
Linux网络(十九):TCP流量控制与滑动窗口详解,超时重传和快重传到底有什么区别
linux·运维·服务器·网络·网络协议·tcp/ip
码上有光7 小时前
Linux进程通信——共享内存、消息队列和信号量
android·linux·运维·共享内存·通信
沫璃染墨7 小时前
《从零入门Linux系统篇(五十四):线程篇·七——互斥锁底层原理:从原子交换到线程竞争与锁实现》
linux·运维·服务器·开发语言·c++·驱动开发·系统架构
Java后端的Ai之路7 小时前
Python进阶探索24_应用案例_linux系统的监控
linux·开发语言·python·应用·探索
H.莓飛8 小时前
【数据结构】队列_OJ题
linux·数据结构·centos
H.莓飛8 小时前
【数据结构】栈_OJ题
linux·数据结构·算法·centos