热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

探究终端会话与孤儿进程组的问题

本文探讨了如何使Shell和程序同时响应Ctrl-C信号的方法,即通过将两者置于同一进程组并将其设为终端的前台进程组。
为了使Shell和某个程序能够同时接收到Ctrl-C信号,最有效的方式是将这两个进程设置在同一进程组,并且将此进程组设置为终端的前台进程组。例如,假设当前终端上的Bash进程PID为2774,可以通过以下C语言代码实现这一目标:

```c
#include
#include
#include

void handler(int n) {
printf("Caught SIGINT\n");
}

int main() {
setpgid(0, 2774); // 将test程序和bash设置为同一进程组
signal(SIGINT, handler);
while (1) {
sleep(1);
// kill(0, SIGINT); // 先注释掉
}
}
```

编译上述代码为`test`,并在运行前设置Bash的陷阱以捕获SIGINT信号:

```bash
trap 'echo Caught SIGINT' INT
```

理想情况下,运行`test`后按下Ctrl-C,屏幕上应显示“Caught SIGINT”和“Caught SIGINT”,但实际上没有任何输出。这涉及到控制终端、进程组等概念。具体来说,当Bash通过fork-exec启动`test`时,已调用`ioctl(fd, TIOCSPGRP, &子进程PID)`,这将子进程(即`test`)的PID设置为TTY的pgrp字段。通过`strace`命令或查看Bash和Linux内核源码可以验证这一点。当内核接收到Ctrl-C时,会将该信号作为普通字符放入终端接收缓冲区,随后调用终端行规程的`receive_buf`处理这些字符。一旦检测到Ctrl-C控制字符,会触发`isig`函数,进而调用`kill_pg(tty->pgrp, sig, 1)`向指定进程组发送信号。由于Bash已将TTY的pgrp更改为`test`的PID,而`test`在调用`setpgid`时从PGID表中脱离,导致没有进程接收到信号。

若取消对`kill`代码行的注释并重新编译运行,虽然`test`能正确显示“Caught SIGINT”,但Bash的相应消息未出现,原因是此时终端被`test`独占,尽管SIGINT已挂起于Bash。要解决这个问题,尝试恢复TTY的pgrp至Bash的PID,例如使用`tcsetpgrp(fd, 2774)`或`ioctl(fd, TIOCSPGRP, &id)`。然而,这些调用均失败,因为`test`无法更改TTY的pgrp。根据POSIX标准,不允许将孤儿进程组设置为TTY的前台进程组,孤儿进程组指组内所有成员要么与其父进程在同一组,要么分属不同会话,从而实现终端信号的隔离。在本例中,`test`设置后的进程组成为孤儿进程组,因此后续的`TIOCSPGRP`调用无效。

若需实现Ctrl-C同时影响两个进程,可在启动`test`时使用后台模式(`test &`),这样Bash不会调用`ioctl`让子进程独占终端,而是保持自身对终端的控制。这样一来,按下Ctrl-C后,两个进程均会响应并输出相应的消息。
推荐阅读
  • 本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • 本文介绍了一款用于自动化部署 Linux 服务的 Bash 脚本。该脚本不仅涵盖了基本的文件复制和目录创建,还处理了系统服务的配置和启动,确保在多种 Linux 发行版上都能顺利运行。 ... [详细]
  • 本文详细解析了Python中的os和sys模块,介绍了它们的功能、常用方法及其在实际编程中的应用。 ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • ImmutableX Poised to Pioneer Web3 Gaming Revolution
    ImmutableX is set to spearhead the evolution of Web3 gaming, with its innovative technologies and strategic partnerships driving significant advancements in the industry. ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 基于KVM的SRIOV直通配置及性能测试
    SRIOV介绍、VF直通配置,以及包转发率性能测试小慢哥的原创文章,欢迎转载目录?1.SRIOV介绍?2.环境说明?3.开启SRIOV?4.生成VF?5.VF ... [详细]
  • 本文探讨了在Java中实现系统托盘最小化的两种方法:使用SWT库和JDK6自带的功能。通过这两种方式,开发者可以创建跨平台的应用程序,使窗口能够最小化到系统托盘,并提供丰富的交互功能。 ... [详细]
  • 深入理解Shell脚本编程
    本文详细介绍了Shell脚本编程的基础概念、语法结构及其在操作系统中的应用。通过具体的示例代码,帮助读者掌握如何编写和执行Shell脚本。 ... [详细]
  • 本文介绍了如何使用 Spring Boot DevTools 实现应用程序在开发过程中自动重启。这一特性显著提高了开发效率,特别是在集成开发环境(IDE)中工作时,能够提供快速的反馈循环。默认情况下,DevTools 会监控类路径上的文件变化,并根据需要触发应用重启。 ... [详细]
  • Java 中的 BigDecimal pow()方法,示例 ... [详细]
  • Java 类成员初始化顺序与数组创建
    本文探讨了Java中类成员的初始化顺序、静态引入、可变参数以及finalize方法的应用。通过具体的代码示例,详细解释了这些概念及其在实际编程中的使用。 ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • 本文由瀚高PG实验室撰写,详细介绍了如何在PostgreSQL中创建、管理和删除模式。文章涵盖了创建模式的基本命令、public模式的特性、权限设置以及通过角色对象简化操作的方法。 ... [详细]
author-avatar
玩玩ftgcriug
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有