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 函数实现。
相关推荐
正在努力的小河40 分钟前
Linux设备树简介
linux·运维·服务器
荣光波比42 分钟前
Linux(十一)——LVM磁盘配额整理
linux·运维·云计算
LLLLYYYRRRRRTT1 小时前
WordPress (LNMP 架构) 一键部署 Playbook
linux·架构·ansible·mariadb
轻松Ai享生活1 小时前
crash 进程分析流程图
linux
大路谈数字化3 小时前
Centos中内存CPU硬盘的查询
linux·运维·centos
luoqice4 小时前
linux下查看 UDP Server 端口的启用情况
linux
倔强的石头_5 小时前
【Linux指南】动静态库与链接机制:从原理到实践
linux
赏点剩饭7785 小时前
linux中的hostpath卷、nfs卷以及静态持久卷的区别
linux·运维·服务器
神鸟云5 小时前
DELL服务器 R系列 IPMI的配置
linux·运维·服务器·网络·边缘计算·pcdn
herderl5 小时前
**僵尸进程(Zombie Process)** 和**孤儿进程(Orphan Process)**
linux·运维·服务器·网络·网络协议