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 函数实现。
相关推荐
Waitccy6 小时前
CentOS 7 离线升级 OpenSSH
linux·运维·centos
黎明晓月7 小时前
Linux 上使用 Docker 部署 Kafka 集群
linux·docker·kafka
清风~徐~来7 小时前
【Linux】应用层协议 HTTP
linux·运维·http
柳如烟@7 小时前
LVS-NAT 负载均衡与共享存储配置
linux·负载均衡·lvs
Forget_85508 小时前
Linux的例行性工作
linux·运维·服务器
用手码出世界8 小时前
自定义minshell
linux·服务器
心随雪冻8 小时前
18.PCIe总线入门理解与Linux上PCIe设备配置与使用
linux·arm开发·嵌入式硬件
m0_745364249 小时前
LVS-DR模式配置脚本
linux·运维·服务器·github·lvs
不知名。。。。。。。。9 小时前
Linux--命令行操作
linux·运维·服务器
老年DBA10 小时前
Linux Namespace(网络命名空间)系列三 --- 使用 Open vSwitch 和 VLAN 标签实现网络隔离
linux·运维·服务器·网络