*nix系统的终端一般会输入Ctrl + D代表输入流结束,Linux和macOS均是如此,尽管Windows用Ctrl + Z,仅仅是外部按键表现,最终目的是一样的。如下以Linux 6.11为例讲解。
- 每开启一个终端会开启一个terminal设备,以tty为例,对应于内核的tty_struct (include\linux\tty.h).
- tty默认配置会定义常见控制按键映射关系:
#define INIT_C_CC { \
[VINTR] = 'C'-0x40, \
[VQUIT] = '\\'-0x40, \
[VERASE] = '\177', \
[VKILL] = 'U'-0x40, \
[VEOF] = 'D'-0x40, \
[VSTART] = 'Q'-0x40, \
[VSTOP] = 'S'-0x40, \
[VSUSP] = 'Z'-0x40, \
[VREPRINT] = 'R'-0x40, \
[VDISCARD] = 'O'-0x40, \
[VWERASE] = 'W'-0x40, \
[VLNEXT] = 'V'-0x40, \
INIT_C_CC_VDSUSP_EXTRA \
[VMIN] = 1 }
上面的VEOF代表文件结束符对应的按键数值是4. - 如上INIT_C_CC会被带入kernel tty标准属性设定 tty_io.c (drivers/tty)
struct ktermios tty_std_termios = { /* for the benefit of tty drivers /
.c_iflag = ICRNL | IXON,
.c_oflag = OPOST | ONLCR,
.c_cflag = B38400 | CS8 | CREAD | HUPCL,
.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN,
.c_cc = INIT_C_CC,
.c_ispeed = 38400,
.c_ospeed = 38400,
/ .c_line = N_TTY, */
}; - 用户层可通过tcgetattr函数获取对应终端tty (struct termios)的c_cc[VEOF]信息,一般而言默认为0x4, 对应于ASCII EOT (End Of Transmission).
- 也可用stty -a命令获取当前tty的设定:
speed 38400 baud; rows 17; columns 198; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = M-^?; eol2 = M-^?; swtch = M-^?; - 综上,Ctrl + D触发按键4,内核根据它注册的EOF传递给上层EOF讯息.