-->

为什么Linux的后按Ctrl + C的总输出“^ C”?(Why Linux always out

2019-07-29 13:56发布

我已经在Linux中一直在研究的信号。 而我做了一个测试程序来捕捉SIGINT。

#include <unistd.h>
#include <signal.h>
#include <iostream>
void signal_handler(int signal_no);
int main() {
  signal(SIGINT, signal_handler);
  for (int i = 0; i < 10; ++i) {
  std::cout << "I'm sleeping..." << std::endl;
  unsigned int one_ms = 1000;
  usleep(200* one_ms);
  }
  return 0;
}
void signal_handler(int signal_no) {
  if (signal_no == SIGINT)
    std::cout << "Oops, you pressed Ctrl+C!\n";
  return;
}

虽然输出如下所示:

I'm sleeping...
I'm sleeping...
^COops, you pressed Ctrl+C!
I'm sleeping...
I'm sleeping...
^COops, you pressed Ctrl+C!
I'm sleeping...
^COops, you pressed Ctrl+C!
I'm sleeping...
^COops, you pressed Ctrl+C!
I'm sleeping...
^COops, you pressed Ctrl+C!
I'm sleeping...
I'm sleeping...
I'm sleeping...

据我所知,按下Ctrl + C时,处理在前台进程组中的所有接收信号情报(如果没有进程选择忽略它)。

那么,这使得外壳(bash)的和上述程序的实例都接收到的信号? 哪里的“^ C”之前每个“哎呀呀”从何而来?

该操作系统是CentOS的,而shell是bash。

Answer 1:

它是截获^ C,并将其转换为发送到连接的过程的信号(其是壳)的终端(驱动程序) stty intr ^B将指示终端驱动程序拦截^ B代替。 它也是呼应了^ C回到终端的终端驱动程序。

壳仅仅是位于在线路的另一端的过程中,并接收它的从终端经由端子驱动器标准输入(例如/ dev / ttyX),并且它的标准输出(和stderr)也连接到相同的TTY 。

需要注意的是(如果启用呼应)终端发送击键到两个处理(组)并返回到终端。 stty命令只是包装器的ioctl()函数,用于“控制” TTY的过程tty驱动。

UPDATE:要证明外壳不参与,我创建了下面的小程序。 应该通过经由它的父shell执行exec ./a.out (它显示一个交互式shell将叉女儿壳,反正)程序设置一个产生^ B,开关回声关闭SIGINTR关键,并且比等待从标准输入。

#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>

int thesignum = 0;
void handler(int signum);

void handler(int signum)
{ thesignum = signum;}

#define THE_KEY 2 /* ^B */

int main(void)
{
int rc;
struct termios mytermios;

rc = tcgetattr(0 , &mytermios);
printf("tcgetattr=%d\n", rc );

mytermios.c_cc[VINTR] = THE_KEY; /* set intr to ^B */
mytermios.c_lflag &= ~ECHO ; /* Dont echo */
rc = tcsetattr(0 , TCSANOW, &mytermios);
printf("tcsetattr(intr,%d) =%d\n", THE_KEY, rc );

printf("Setting handler()\n" );
signal(SIGINT, handler);

printf("entering pause()\n... type something followed by ^%c\n", '@'+THE_KEY );
rc = pause();
printf("Rc=%d: %d(%s), signum=%d\n", rc, errno , strerror(errno), thesignum );

// mytermios.c_cc[VINTR] = 3; /* reset intr to ^C */
mytermios.c_lflag |= ECHO ; /* Do echo */
rc = tcsetattr(0 , TCSANOW, &mytermios);
printf("tcsetattr(intr,%d) =%d\n", THE_KEY, rc );

return 0;
}

intr.sh:

#!/bin/sh
echo $$
exec ./a.out
echo I am back.


Answer 2:

外壳相呼应,你输入的一切,所以当你键入^C ,即得得到呼应(和你的情况通过信号处理程序截获)。 该命令stty -echo可能会或可能不会根据您的需要/约束是对你有用,看到了stty的手册页了解更多信息。

在较低的水平,当然更推移, 任何时候你经由外围设备的设备驱动程序与系统通信(如您使用以产生^ C信号键盘驱动程序,以及显示一切终端驱动程序)参与。 如果你想理解下面的书籍更详细,深入的级别是开始的好地方,你可以挖在汇编/机器语言,寄存器,查找表等的水平甚至更深:

Unix的OS的设计是这些形式的东西一个很好的参考。 两个比较经典引用: Unix的编程环境和UNIX环境高级编程

在这所很好的总结SO问题如何按Ctrl-C终止子进程?

“什么时候你运行一个程序,例如find ,外壳:

  • 外壳本身叉
  • 并为孩子设置默认的信号处理
  • 与给定的命令替换子(例如与find)
  • 当您按下CTRL-C,父shell处理这个信号,但孩子将收到它 - 用默认的动作 - 终止。 (孩子能实现信号处理过)”


文章来源: Why Linux always output “^C” upon pressing of Ctrl+C?