Posts 再读APUE——再聊进程
Post
Cancel

再读APUE——再聊进程

1. 会话

意义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 1. 会话的意义
会话的核心确实是 ​​统一管理进程与终端的交互​​,但它​​不仅限于前台任务,也会管理后台任务​​。尤其是在多任务、后台任务、终端断开等场景下。

- 你打开的终端(如 bash)就是一个 ​​会话​​。
- 在这个终端中运行的所有命令(如 vim, top, ping)都属于这个会话的子进程。
- 会话的作用​​:将这些进程“捆绑”在一起,方便统一管理(比如终端断开时,内核需要知道哪些进程应该被终止或保留)。

// 2. 前后台任务,如何区分前后台任务?​
在同一个终端中,你可能同时运行多个任务:
- 前台任务(如 vim):直接与终端交互。
- 后台任务(如 sleep 100 &):不占用终端输入。
- 通过 ​​进程组(Process Group)​​ 将会话内的进程分组,终端只与前台进程组交互。

// 3. 怎么理解 ​进程组(Process Group)​​ 将会话内的进程分组,终端只与前台进程组交互。
每个会话在任意时刻,​​只有一个进程组是“前台进程组”​​,其他进程组都是后台进程组。

// 4. 如何实现“持久化”任务?​
tmux  screen 会创建一个 ​​独立的会话​​,即使终端断开,会话仍存在(因为会话不再绑定到原终端)。

// 5. 如何查看当前进程的后台任务
jobs -l  

守护进程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 什么是守护进程
守护进程(Daemon Process)​​  Linux/Unix 系统中的一种特殊后台进程,通常在系统启动时运行,​​脱离终端控制​​,长期提供服务(如网络、日志、定时任务等)。它的核心特点是 ​​无终端关联、独立运行、生命周期长​​。

// 创建守护进程举例
// 关键步骤: fork() → setsid() → 重定向标准流 → 脱离文件系统。
// 现代linux 实践:使用 systemd 控制
int main() {
    pid_t pid = fork();
    if (pid > 0) exit(0);  // 父进程退出

    setsid();               // 创建新会话
    chdir("/");             // 切换工作目录
    umask(0);               // 重置文件权限掩码

    // 关闭所有文件描述符(可选)
    for (int i = sysconf(_SC_OPEN_MAX); i >= 0; i--) close(i);

    // 重定向标准流
    freopen("/dev/null", "r", stdin);
    freopen("/dev/null", "w", stdout);
    freopen("/dev/null", "w", stderr);

    // 守护进程的主逻辑
    while (1) {
        // 例如:每隔 10 秒写入日志
        system("echo 'Daemon is running...' >> /var/log/mydaemon.log");
        sleep(10);
    }
    return 0;
}

聊聊 systemd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// waf systemd 单元
root>cat /lib64/systemd/system/cneos.service
[Unit]
Description=cneos start service  # 服务的描述信息,方便管理员识别。
Before=network.target sshd.service  #表示该服务会在 network.target(网络就绪)和 sshd.serviceSSH 服务)​​之前启动​​。

[Service]
Type=forking  # 1. 表示服务启动时会 ​​fork 子进程​​,并且父进程会退出(传统守护进程行为)。
              # 2. start_service.sh 必须 ​​后台化​​(如使用 & 或 setsid),否则 systemd 会认为服务启动失败。
ExecStart=/bin/bash /bin/start_service.sh  # 通过 bash 执行 /bin/start_service.sh
TimeoutStartSec=0  # 禁用启动超时,即允许服务无限期启动(适用于长时间初始化)。
KillMode=none   # 当停止服务时,​​不杀死任何进程​​(即使主进程退出,子进程仍继续运行)。
[Install]
WantedBy=multi-user.target  # 通过 systemctl enable cneos.service 启用后,开机时会自动运行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 什么是systemctl 
1. systemctl  ​​Linux 系统和服务管理器(systemd)​​ 的核心命令行工具,用于​​管理系统服务、守护进程、挂载点、套接字等资源​​。
​​2. systemd​​  Linux 的初始化系统

// 常见命令
sudo systemctl start cneos.service  # 启动服务
sudo systemctl status cneos.service # 状态检查
sudo systemctl enable cneos.service # 开机自启
journalctl -u cneos.service -f  # 实时日志  

// 怎么查看 服务是否注册 systemctl
systemctl list-units --type=service  // 之前waf串口登录失败可看tty 串口服务是否启动

// 怎么查看对应systemctl 日志
sudo journalctl -u getty@tty0.service

哪些进程在终端终止后会退出

命令终端关闭后是否被终止说明
python xxx.py前台进程,属于当前会话。
python xxx.py &后台进程,但仍属于当前会话。
nohup python xxx.py &忽略 SIGHUP,进程继续运行。
setsid python xxx.py创建新会话,完全脱离原终端。
(python xxx.py &)子 shell 退出后,进程仍属于原会话(除非配合 disown)。
tmux new-session -d 'python xxx.py'tmux 独立会话中运行,脱离原终端。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 0. python xxx.py &
不同的终端, 这个表现不一样。 有些终端退出后这个并不会被一起退出。

// 1. 如何查看当前进程的后台任务
jobs -l  

// 2. ctl + c && ctl + z 有什么区别?
root>jobs -l
[1]   8640 Stopped                 tail -f /var/log/wafd.log
      8641                       | grep ABSORB_STAR  (wd: ~)
[2]-  6236 Stopped                 tail -f /var/log/wafd.log
      6237                       | grep ABSORB_STAR  (wd: ~)
[3]+ 22304 Stopped                 journalctl -u cneos.service -f

一个是暂停 一个是退出
Ctrl + Z​​  ​​Ctrl + C​​ 是完全不同的操作,它们分别发送不同的信号并产生不同的行为

setsid

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// setsid 是一个 Linux/Unix 命令和系统调用,用于 ​​创建一个新的会话(Session)​​,并让当前进程成为该会话的首进程(Session Leader)。它的核心作用是 ​​脱离原终端的控制​​,常用于守护进程(Daemon)或需要独立运行的进程

// fork() + setsid()​​ 是创建守护进程的标准方式。
int main() {
    pid_t pid = fork();
    if (pid == 0) {  // 子进程
        setsid();    // 创建新会话,脱离原终端
        // 守护进程逻辑...
        while (1) {
            // do something
        }
    }
    return 0;
}

2. 作业调度

命令作用描述示例
jobs列出当前Shell会话中的所有作业及其状态jobs -l
fg %n将作业n切换到前台运行fg %1
bg %n将作业n切换到后台运行bg %2
kill %n终止作业nkill %3
1
2
3
4
5
6
root>jobs
[3]-  已停止               tail -f /var/log/wafd.log | grep solution
[4]+  已停止               find / -name "libthread_db*"

root>fg %1
tail -f /var/log/wafd.log | grep solution       (wd: /opt/data/engine_coredump)
This post is licensed under CC BY 4.0 by the author.

Contents

Trending Tags