根据这页面中,此字段描述“行规则”,它确定当用户按退格键或 ^C 时会发生什么。本质上,当程序调用read(2)
.
不过设置好像没有什么效果。在我的 Linux 机器上,我有两条线路规则:
$ cat /proc/tty/ldiscs
n_tty 0
n_null 27
但$ stty line 27
似乎没有影响任何事情。退格键仍然正常工作。
然而,如果我这样做$ stty -icanon
,我确实会看到一个变化——退格键不再正常工作,程序会逐个字符地读取内容(read(2)
似乎总是只返回 1 个字符)。
这里发生了什么?
答案1
线路规则是 tty 驱动程序和 tty 核心之间的一层(参见这张图片,来自这里):
如果将其设置为 27 (tty_null),您的日期将穿过图表的左侧(跳过行规则)。如果将其设置为 0,则它会通过默认的线路规则,可以处理原始输入和煮熟的输入。
TTY(0)
The default line discipline, providing transparent operation (raw mode)
as well as the habitual terminal line editing capabilities (cooked mode).
其他学科的列表是这里。
您可以自己编写,也可以使用现有的。如果您拥有该slip
模块并将其插入modprobe slip
,您会注意到这一点:
$ cat /proc/tty/ldiscs
n_tty 0
slip 1
n_null 27
当您这样做时,$ stty line 27
您删除了线路规则(您将其设置为空线路规则),当您这样做时,$ stty -icanon
您在原始模式下设置了默认线路规则。
答案2
stty line N
没有做太多事情。
要更改 Linux 上的线路规则,应该调用ioctl(TIOCSETD)
,但它并没有这样做;stty line N
只是更改 termios 结构的(非标准)c_line
字段,然后调用tcsetattr(3)
-> ioctl(TCSETS*)
,这将简单地更改后续->c_line
调用返回的字段。tcgetattr(3)
ioctl(TCGETS)
在这个答案的最后是一个小的 C 示例程序,它应该真正改变其 stdin fd 上的行规则。
这并不是唯一stty(1)
不足的方法;stty
也无法设置“非标准”波特率(这可以在 Linux 上使用TCSETS2
// TCSETSW2
ioctl轻松完成TCSETSF2
,但不幸的是它没有在标准 C 库中公开,并且不被 所使用stty
)。
$ cat > tiocsetd.c <<'EOT'
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <err.h>
int main(int ac, char **av){
int o;
if(ioctl(0, TIOCGETD, &o)) err(1, "io(TIOCGETD)");
if(ac > 1){
int n, d = atoi(av[1]);
if(ioctl(0, TIOCSETD, &d)) err(1, "io(TIOCSETD)");
if(ioctl(0, TIOCGETD, &n)) err(1, "io(TIOCGETD)");
printf("%d -> %d => %d\n", o, d, n);
}else
printf("%d\n", o);
return 0;
}
EOT
$ cc -Wall tiocsetd.c -o tiocsetd
$ ./tiocsetd
0
$ tty
/dev/pts/4 ## << make a note of this
$ cat /proc/tty/ldiscs
n_tty 0
n_null 27
$ ./tiocsetd 27
<your tty is hugged ;-)>
要恢复它,请./tiocsetd 0 </dev/pts/4
从另一个终端运行(替换/dev/pts/4
为实际的 tty),然后按^C
。