Why Linux always output “^C” upon pressing of Ctrl+C?

前端 未结 2 2157
生来不讨喜
生来不讨喜 2021-02-15 15:08

I have been studying signals in Linux. And I\'ve done a test program to capture SIGINT.

#include 
#include 
#include 

        
2条回答
  •  半阙折子戏
    2021-02-15 15:16

    It is the terminal (driver) that intercepts the ^C and translates it to a signal sent to the attached process (which is the shell) stty intr ^B would instruct the terminal driver to intercept a ^B instead. It is also the terminal driver that echoes the ^C back to the terminal.

    The shell is just a process that sits at the other end of the line, and receives it's stdin from your terminal via the terminal driver (such as /dev/ttyX), and it's stdout (and stderr) are also attached to the same tty.

    Note that (if echoing is enabled) the terminal sends the keystrokes to both the process (group) and back to the terminal. The stty command is just wrapper around the ioctl()s for the tty driver for the processes "controlling" tty.

    UPDATE: to demonstrate that the shell is not involved, I created the following small program. It should be executed by its parent shell via exec ./a.out (it appears an interactive shell will fork a daughter shell, anyway) The program sets the key that generates the SIGINTR to ^B, switches echo off, and than waits for input from stdin.

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    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.
    

提交回复
热议问题