【问题标题】:process catch SIGINT signal using sigint_handler进程使用 sigint_handler 捕获 SIGINT 信号
【发布时间】:2020-05-25 06:58:23
【问题描述】:

我在CSAPP一书中做shell实验室时遇到了这个问题,实验室要求你用一些规范实现自己的shell版本,其中之一是

键入 ctrl-c (ctrl-z) 应该会导致 SIGINT (SIGTSTP) 信号 发送到当前前台作业,以及该作业的任何后代 作业(例如,它派生的任何子进程)。如果没有 前台工作,那么信号应该没有效果。

所以你应该完成一个名为 sigint_handler 的给定函数,它应该捕获 SIGINT 信号并将其发送到前台作业。下面是我在网上找到的一段代码(代码通过了正确性检查)

void sigint_handler(int sig) 
{
    int olderrno = errno;
    pid_t pid = fgpid(jobs);
    if (pid != 0)
        kill(-pid, sig);
    errno = olderrno;
    return;
}

我不明白的是,如果 SIGINT 是使用 kill 发送的,那么前台作业的后代也会使用这个处理程序来捕获 SIGINT 信号,对吗?所以这是对我的一种递归调用。那么这实际上是如何工作的?谢谢你帮助我。

处理程序安装在主函数中

signal(SIGINT,  sigint_handler);   /* ctrl-c */

和 fgpid 返回当前前台作业的 PID,如果没有这样的作业,则返回 0

【问题讨论】:

  • 我们没有看到所有的代码。处理程序安装在哪里?它是如何安装的? fgpid 返回什么?如果fgpid 在后代作业中返回pid = 0 怎么办?这不算作停止条件吗?
  • 我更新了问题描述

标签: c linux shell


【解决方案1】:

一旦子进程调用execve(),子进程的(通常是短暂的)初始地址空间被释放/释放并替换为指定可执行映像的空间;现在,孩子不再拥有对父母数据或文本的副本或访问权限,例如信号处理程序。

现在考虑一个与控制终端 (tty) 关联的进程组。当用户键入 CTRL-C(或 CTRL-\ 或 CTRL-Z)时,tty 驱动程序将信号发送给 1+ 进程作为关联进程组的成员。除非进程建立了不同的信号处置(signal()sigaction() 或相关),否则传递信号的结果将是系统默认操作。

发布的代码摘录表明一个中继事件:用户键入一个 CTRL-C,tty 驱动程序向 shell 发送一个 SIGINT,shell 的处理程序寻找一个前台作业,调用 kill() 和一个否定的 pid 来发布一个信号给该进程组的成员。

有关相关信息,请参阅这些手册页:

man setpgrp
man tty_ioctl  (symbols: TIOCSCTTY, TIOCGPGRP, TIOCSPGRP)

alternates:
man tcgetpgrp tcsetpgrp

【讨论】:

  • 谢谢,所以如果我只使用 fork 来创建子进程而不执行 execve 子进程将使用相同的 sigint_handler 对吗?
猜你喜欢
  • 2017-08-22
  • 2016-04-05
  • 2015-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-05
相关资源
最近更新 更多