当前位置: 首页 > news >正文

bash 启动程序的流程

文章目录

  • 1. 启动流程概要
  • 2. 实践
    • 2.1 新进程的 Process Group 观察
    • 2.2 在 bash 启动的程序里创建新 session
  • 3. 番外

1. 启动流程概要

bash 启动程序的 3 个主要步骤:fork() + setpgid() + exec*()

image

为什么 bash 要对新进程调用 setpgid()、将其放入一个独立的 Process Group 呢?主要原因如下:

  • bash job 控制。如果不将新程序放入独立的 Process Group,则新程序进程将继承父进程 bash 的 Process Group,这样 fg/bg/jobs 程序将无法 Process Group 唯一标识来控制新程序(这些程序按 PGID 进行操作);

  • 独立处理信号。如果 bash 不将新启动的程序放入独立 Process Group,则所有启动的进程都将位于和 bash 同一 Process Group 内。发给某个 (bash 启动的)程序的 Ctrl+C 等信号,将会传递给 bash 和其启动所有程序所在的同一 Process Group,从而使 bash 及其启动的程序都终止(自身配置了信号处理的程序除外);

  • bash 管道处理。像 cmd1 | cmd2 | cmd3 管道命令,如果不放入独立 Process Group,则无法当都当作一个 job 来控制处理;相反,则可以通过独立的 PGID 来 job 控制。

2. 实践

2.1 新进程的 Process Group 观察

$ cat t.c
#include <unistd.h>void main(void)
{while (1) sleep(8);
}
$ ./t &
[1] 4612
$ ps -eo pid,ppid,pgid,sid,commPID    PPID    PGID     SID COMMAND1       0       1       1 systemd
[......]4598    4580    4598    4598 bash4612    4598    4612    4598 t
[......]

从上面的 ps 命令输出信息看到:

  • 程序 tPPID == 4598,也即 bashPID,所以 t 是由 bash 启动的;
  • 程序 tPID == PGID == 4612,所以 t 位于独立的 Process Group 4612 中;

2.2 在 bash 启动的程序里创建新 session

Linux 通过 setsid() 新建一个 Session。下面的 setsid_test 程序,试图通过 setsid() 新建立一个 session

#include <unistd.h>
#include <stdio.h>int main(void)
{pid_t sid;sid = setsid();if (sid == -1) {perror("setsid");return -1;}printf("new session: %d\n", sid);while (1) sleep(8);return 0;
}

编译,然后从 bash 终端启动:

$ ./setsid_test
setsid: Operation not permitted

结果失败了,报 EPERM 错误。glibcsetsid() 是对系统接口 sys_setsid() 的直接调用,看下 sys_setsid() 的内核代码:

SYSCALL_DEFINE0(setsid)
{struct task_struct *group_leader = current->group_leader; // group_leader == current,指向 setsid_teststruct pid *sid = task_pid(group_leader);pid_t session = pid_vnr(sid);int err = -EPERM;write_lock_irq(&tasklist_lock);/* Fail if I am already a session leader */if (group_leader->signal->leader)goto out;/* Fail if a process group id already exists that equals the* proposed session id.*//* 如果进程已经是 Process Group Leader,则返回错误码 EPERM */if (pid_task(sid, PIDTYPE_PGID))goto out; /* (1) *//* 进程成为新的 Process Group/Session Leader */group_leader->signal->leader = 1;set_special_pids(sid);/* 断开与 tty 终端的连接 */proc_clear_tty(group_leader);err = session;
out:write_unlock_irq(&tasklist_lock);if (err > 0) {proc_sid_connector(group_leader);sched_autogroup_create_attach(group_leader);}return err;
}

测试程序 setsid_testsetsid() 调用在上面代码标注 (1) 处返回,表示进程已经是一个Process Group Leader,而 Linux 规定已经是 Process Group Leader 不能成为新的 Session Leader。如何解决这个问题?方案一是通过 fork() 调用:fork() 后,首先退出父进程,以摆脱 bash 通过 setpgid() 设置的 leader 身份;然后再在子进程中调用 setsid() 将会成功,因为子进程不具备 leader 身份,这正是 glibc 库函数 daemon() 采用的方式;另一个解决方案是不通过 bash 启动程序,而是通过 /etc/rc.localSystemV 的 init script 启动程序。

那为什么不允许 Process Group Leader 成为 Session Leader ?因为一旦允许, 由于 setsid() 新成立了 SessionProcess Group,所以 Process Group Leader 将进入新的 Process GroupSession,这样在原本 Process Group 内进程将失去它们的 Process Group Leader, 这样会引发歧义,同时使得像 bashjob control 也将无法工作。如果你无法理解这些逻辑,就简单的理解为这是 Linux 内核的强制规定就可以了。

我们使用 glibcdaemon() 接口来创建 Sessiondaemon() 通过 fork() 之后的子进程调用 setsid(),而 父进程则退出以摆脱 bash 赋予的 Process Group Leader 角色。修改后的代码如下:

#include <unistd.h>
#include <stdio.h>int main(void)
{pid_t sid;#if 1if (daemon(0, 0) != 0) {perror("daemon");return -1;}sid = getsid(0);
#elsesid = setsid();if (sid == -1) {perror("setsid");return -1;}
#endifprintf("new session: %d\n", sid);while (1) sleep(8);return 0;
}
$ ./setsid_test
[2] 4864$ ps -eo pid,ppid,pgid,sid,commPID    PPID    PGID     SID COMMAND1       0       1       1 systemd
[......]2173       1    2173    2173 systemd
[......]4598    4580    4598    4598 bash
[......]4865    2173    4865    4865 setsid_test
[......]

首先观察到,setsid_testprintf() 输出的内容并没有看到,因为 setsid() 会断开与 tty 终端的连接;然后从 ps 命令输出也观察到,setsid_testPID == PGID == SID == 4865,且 PPID == 2173,指向 systemd,而不是 bash,因为 fork() 的父进程退出了,保留了子进程,被托孤给了 systemd

3. 番外

笔者在内核代码进程创建、程序加载执行、进程 SID 设置处加入一些,可以帮助理解本文内容(修改源码就不贴了):

[    2.769850] sys_setsid()-2#: current@ffff800035330000,systemd,1,1 group_leader@ffff800035330000,systemd, pgrp@          (null),(null), session@          (null),(null)
[    5.475602] sys_setsid()-2#: current@ffff800034afab80,(journald),1357,1357 group_leader@ffff800034afab80,(journald), pgrp@          (null),(null), session@          (null),(null)
[    5.533479] sys_setsid()-2#: current@ffff800034afba00,(modprobe),1358,1358 group_leader@ffff800034afba00,(modprobe), pgrp@          (null),(null), session@          (null),(null)
[    5.605649] sys_setsid()-2#: current@ffff800034afc880,(modprobe),1359,1359 group_leader@ffff800034afc880,(modprobe), pgrp@          (null),(null), session@          (null),(null)
[    5.668971] sys_setsid()-2#: current@ffff800034afd700,(modprobe),1360,1360 group_leader@ffff800034afd700,(modprobe), pgrp@          (null),(null), session@          (null),(null)
[    5.708364] sys_setsid()-2#: current@ffff800034488000,(modprobe),1361,1361 group_leader@ffff800034488000,(modprobe), pgrp@          (null),(null), session@          (null),(null)
[    5.763098] sys_setsid()-2#: current@ffff800034488e80,(les-load),1362,1362 group_leader@ffff800034488e80,(les-load), pgrp@          (null),(null), session@          (null),(null)
[    5.808880] sys_setsid()-2#: current@ffff800034489d00,(mount-fs),1363,1363 group_leader@ffff800034489d00,(mount-fs), pgrp@          (null),(null), session@          (null),(null)
[    6.372598] sys_setsid()-2#: current@ffff80003448ba00,(dom-seed),1366,1366 group_leader@ffff80003448ba00,(dom-seed), pgrp@          (null),(null), session@          (null),(null)
[    6.508326] sys_setsid()-2#: current@ffff80003448c880,(d-sysctl),1367,1367 group_leader@ffff80003448c880,(d-sysctl), pgrp@          (null),(null), session@          (null),(null)
[    6.695839] sys_setsid()-2#: current@ffff800034afe580,(sysusers),1368,1368 group_leader@ffff800034afe580,(sysusers), pgrp@          (null),(null), session@          (null),(null)
[    7.067327] sys_setsid()-2#: current@ffff80003448d700,(urnalctl),1371,1371 group_leader@ffff80003448d700,(urnalctl), pgrp@          (null),(null), session@          (null),(null)
[    7.285510] sys_setsid()-2#: current@ffff80003448e580,(tmpfiles),1372,1372 group_leader@ffff80003448e580,(tmpfiles), pgrp@          (null),(null), session@          (null),(null)
[    7.788486] sys_setsid()-2#: current@ffff800034448000,(tmpfiles),1374,1374 group_leader@ffff800034448000,(tmpfiles), pgrp@          (null),(null), session@          (null),(null)
[    8.395642] sys_setsid()-2#: current@ffff800034afd700,(resolved),1375,1375 group_leader@ffff800034afd700,(resolved), pgrp@          (null),(null), session@          (null),(null)
[    8.460479] sys_setsid()-2#: current@ffff800034afc880,(imesyncd),1376,1376 group_leader@ffff800034afc880,(imesyncd), pgrp@          (null),(null), session@          (null),(null)
[    8.508925] sys_setsid()-2#: current@ffff800034afba00,(ate-utmp),1377,1377 group_leader@ffff800034afba00,(ate-utmp), pgrp@          (null),(null), session@          (null),(null)
[   10.588649] sys_setsid()-2#: current@ffff800034afba00,(s-daemon),1379,1379 group_leader@ffff800034afba00,(s-daemon), pgrp@          (null),(null), session@          (null),(null)
[   10.731695] sys_setsid()-2#: current@ffff800034afe580,(crub_all),1380,1380 group_leader@ffff800034afe580,(crub_all), pgrp@          (null),(null), session@          (null),(null)
[   10.868722] sys_setsid()-2#: current@ffff800034af9d00,(spatcher),1383,1383 group_leader@ffff800034af9d00,(spatcher), pgrp@          (null),(null), session@          (null),(null)
[   11.041570] sys_setsid()-2#: current@ffff800034af8e80,(d-logind),1384,1384 group_leader@ffff800034af8e80,(d-logind), pgrp@          (null),(null), session@          (null),(null)
[   11.139285] sys_setsid()-2#: current@ffff800034af8000,(sessions),1385,1385 group_leader@ffff800034af8000,(sessions), pgrp@          (null),(null), session@          (null),(null)
[   16.689700] sys_setsid()-2#: current@ffff800034449d00,(agetty),1387,1387 group_leader@ffff800034449d00,(agetty), pgrp@          (null),(null), session@          (null),(null)
[   16.694360] sys_setsid()-2#: current@ffff800034448e80,(agetty),1386,1386 group_leader@ffff800034448e80,(agetty), pgrp@          (null),(null), session@          (null),(null)
[   95.171292] sys_setsid()-2#: current@ffff800034af8000,(ate-utmp),1402,1402 group_leader@ffff800034af8000,(ate-utmp), pgrp@          (null),(null), session@          (null),(null)
[  180.544365] sys_setsid()-2#: current@ffff80003444c880,(time-dir),1412,1412 group_leader@ffff80003444c880,(time-dir), pgrp@          (null),(null), session@          (null),(null)
[  180.821462] sys_setsid()-2#: current@ffff80003444d700,(systemd),1413,1413 group_leader@ffff80003444d700,(systemd), pgrp@          (null),(null), session@          (null),(null)
[  181.911442] SYSC_setpgid(): p@ffff8000321be580,bash,1419,1419 current@ffff8000321be580,bash,1419,1419 current_group@ffff8000321be580,bash,1419,1419 pgrp@ffff8000320f4600
[  181.959156] copy_process(): init_struct_pid@ffff200009b56520
[  181.959307] copy_process()-1#: p@ffff800031610000,bash,1420,1420 p->group_leader@ffff800031610000,bash,1420,1420 current@ffff8000321be580,bash,1419,1419 current_group@ffff8000321be580,bash,1419,1419 task_pgrp(current)=ffff8000320f4600, task_session(current)=ffff800033f1f480
[  181.972394] SYSC_execve(): /usr/bin/groups current@ffff800031610000,bash,1420,1420
[  182.028751] copy_process()-1#: p@ffff800031610e80,bash,1421,1421 p->group_leader@ffff800031610e80,bash,1421,1421 current@ffff8000321be580,bash,1419,1419 current_group@ffff8000321be580,bash,1419,1419 task_pgrp(current)=ffff8000320f4600, task_session(current)=ffff800033f1f480
[  182.080254] copy_process()-1#: p@ffff800031611d00,bash,1422,1422 p->group_leader@ffff800031611d00,bash,1422,1422 current@ffff8000321be580,bash,1419,1419 current_group@ffff8000321be580,bash,1419,1419 task_pgrp(current)=ffff8000320f4600, task_session(current)=ffff800033f1f480
[  182.134983] copy_process()-1#: p@ffff800031612b80,bash,1423,1423 p->group_leader@ffff800031612b80,bash,1423,1423 current@ffff8000321be580,bash,1419,1419 current_group@ffff8000321be580,bash,1419,1419 task_pgrp(current)=ffff8000320f4600, task_session(current)=ffff800033f1f480[  192.925429] copy_process()-1#: p@ffff800031613a00,bash,1424,1424 p->group_leader@ffff800031613a00,bash,1424,1424 current@ffff8000321be580,bash,1419,1419 current_group@ffff8000321be580,bash,1419,1419 task_pgrp(current)=ffff8000320f4600, task_session(current)=ffff800033f1f480
[  192.928675] SYSC_setpgid(): p@ffff800031613a00,bash,1424,1424 current@ffff800031613a00,bash,1424,1424 current_group@ffff800031613a00,bash,1424,1424 pgrp@ffff80002fc70200
[  192.939927] SYSC_execve(): ./setsid_test current@ffff800031613a00,bash,1424,1424
[  192.965327] sys_setsid()-1#: current@ffff800031613a00,setsid_test,1424,1424 group_leader@ffff800031613a00,setsid_test,1424,1424 pgrp@ffff800031613a00,setsid_test,1424,1424 session@          (null),(null)[  213.538658] copy_process()-1#: p@ffff800031614880,bash,1425,1425 p->group_leader@ffff800031614880,bash,1425,1425 current@ffff8000321be580,bash,1419,1419 current_group@ffff8000321be580,bash,1419,1419 task_pgrp(current)=ffff8000320f4600, task_session(current)=ffff800033f1f480
[  213.539338] SYSC_setpgid(): p@ffff800031614880,bash,1425,1425 current@ffff8000321be580,bash,1419,1419 current_group@ffff8000321be580,bash,1419,1419 pgrp@ffff80002fc70280
[  213.546247] copy_process()-1#: p@ffff800031418000,bash,1426,1426 p->group_leader@ffff800031418000,bash,1426,1426 current@ffff8000321be580,bash,1419,1419 current_group@ffff8000321be580,bash,1419,1419 task_pgrp(current)=ffff8000320f4600, task_session(current)=ffff800033f1f480
[  213.546731] SYSC_setpgid(): p@ffff800031418000,bash,1426,1426 current@ffff8000321be580,bash,1419,1419 current_group@ffff8000321be580,bash,1419,1419 pgrp@ffff80002fc70280
[  213.558916] SYSC_execve(): /usr/bin/dmesg current@ffff800031614880,bash,1425,1425
http://www.dtcms.com/a/597266.html

相关文章:

  • 专题:2025中国医疗器械出海现状与趋势创新发展研究报告|附160+份报告PDF、数据、可视化模板汇总下载
  • 工程建设最好的网站石家庄建设网站哪家好
  • c#笔记之面向对象
  • wordpress 移动到回收站发生错误广告公司网络推广计划
  • 汽车乘员热舒适测评的预测模型
  • [6]. SpringAI Alibaba 向量化和向量数据库
  • java学习--包
  • 乐鑫EchoEar开发套件详解:ESP32-S3+端侧AI+全双工语音实战
  • 国外的外贸网站wordpress 页面下文章列表
  • 站长工具服务器查询常州市建设工程管理中心网站
  • 《实施意见》绘就场景应用蓝图,政务服务如何找准自身“坐标”
  • Go 优雅关闭实践指南:从原理到框架落地
  • 使用gRPC实现分片服务的心跳机制
  • 陕西建设厅执业注册中心网站重庆网站建设沛宣
  • 济南 外贸网站建设大连鼎信网站建设公司地址
  • 自动化渗透工具分类及主流工具详解(2025年最新)
  • Qt QPushButton 样式完全指南:从基础到高级实现
  • 在Unity3d中使用Netly开启TCP服务
  • 男男床做视频网站上海家装设计网站
  • 如何清空网站空间上海工程建设招投标网站
  • Docker-玩转 Docker 镜像:从拉取、构建到发布
  • 技师院校人工智能技术应用专业实训室建设方案
  • HarmonyOS Tabs标签页组件深度解析:超越基础的高级技巧与实践
  • 无锡网站建设推荐wordpress 的分类目录
  • elasticSearch之java客户端详细使用:文档搜索API
  • 网页美工设计网站运维工程师可以自学吗
  • 手机网站制作注意事项卖产品的网站怎么做
  • Vue3 + Pinia 移动端Web应用:页面缓存策略解决方案
  • 可视化智能动作测评系统:用数据重塑每一个动作的科学评估时代
  • 算法32.0