微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么Linux在按下Ctrl C时总是输出“^ C”?

我一直在研究 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...
I'm sleeping...
I'm sleeping...

据我所知,当按下Ctrl C时,前台进程组中的进程都会收到一个SIGINT(如果没有进程选择忽略它).

那么shell(bash)和上面程序的实例都收到了信号吗?每个“哎呀”之前的“^ C”来自哪里?

操作系统是CentOS,shell是bash.

解决方法

终端(驱动程序)拦截^ C并将其转换为发送到附加进程(即shell)的信号,stty intr ^ B将指示终端驱动程序拦截^ B.它也是将^ C回送到终端的终端驱动程序.

shell只是一个位于该行另一端的进程,并通过终端驱动程序(例如/ dev / ttyX)从终端接收它的stdin,并且它的stdout(和stderr)也附加到同一个tty .

注意(如果启用了回显),终端将击键发送到进程(组)并返回到终端. stty命令只是用于“控制”tty的进程的tty驱动程序的ioctl()的包装.

更新:为了证明shell没有参与,我创建了以下小程序.它应该由它的父shell通过exec ./a.out执行(看起来交互式shell会分叉一个子shell,无论如何)程序将生成SIGINTR的键设置为^ B,关闭echo,然后等待来自stdin的输入.

#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,rc );

return 0;
}

intr.sh:

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐