【问题标题】:How does launching `less` differ from launching `cat` in ZSH with regards to the usage of alternate screen and background suspension在使用备用屏幕和背景暂停方面,在 ZSH 中启动 `less` 与启动 `cat` 有何不同
【发布时间】:2016-08-17 07:27:22
【问题描述】:

在我的操作系统上,默认情况下,ZSH 有 -tostop(或者是 tty?)。

这允许后台进程在有输出时输出到 shell。

因此:

> stty -tostop
> echo 'random' >/tmp/random
> cat /tmp/random &
[1] 7588
random
[1]  + 7588 done       cat /tmp/random

相应地:

> stty tostop
> echo 'random' >/tmp/random
> cat /tmp/random &
[1] 3888
[1]  + 3888 suspended (tty output)  cat /tmp/random

阅读文档并尝试了一下,我发现 ZSH 有 4 种类型的挂起进程(您可以使用 kill -$SIGNAL $PID ; jobs 看到这一点):

job state              - signal that gives you job state
suspended              - SIGTSTP
suspended (signal)     - SIGSTOP
suspended (tty input)  - SIGTTIN
suspended (tty output) - SIGTTOU

这意味着3888 进程正在接收SIGTTOU 信号。

这一切都说得通。

现在我的问题是,为什么less 不受stty tostopstty -tostop 的影响?

> stty tostop
> less /tmp/random &
[1] 6300
[1]  + 6300 suspended (tty output)  less --LONG-PROMPT --chop-long-lines /tmp/random

> stty -tostop
> less /tmp/random &
[1] 4808
[1]  + 4808 suspended (tty output)  less --LONG-PROMPT --chop-long-lines /tmp/random

正如您在这两种情况下看到的那样,less 总是在后台暂停。

现在,我知道了less -X,我也知道了终端模拟器的备用屏幕功能。 事实上,你可以用less -X 运行上面两个命令,它会导致同样的暂停。 即使-X 使它不使用备用屏幕,less 仍然得到suspended (tty output)

我想知道的是less 总是被suspended (tty output) 暂停的实际机制,即使tostop 被切换,即使-X 也被切换。 shell 怎么能一直发送SIGTTOUless,除非有其他方式less 被挂起。

【问题讨论】:

  • 备用屏幕与less 中的信号处理无关。

标签: terminal signals zsh terminal-emulator less-unix


【解决方案1】:

(你没有指定你的操作系统,但这个答案是基于 linux 的)

使用strace,您可以看到stty 在fd 0 (stdin) 上执行ioctl,在termios 结构的c_lflag 值中切换一位。

strace 还透露less 将打开/dev/tty 并在其上发出ioctl 以更改c_lflag

所以less 只是在输出任何东西之前和stty tostop 做同样的事情。

【讨论】:

  • 我明白了。当您说“fd 0 (stdin)”时,您指的是外壳本身的标准输入吗?否则,您指的是哪个标准输入?因此,当 less 打开文件时,它实际上会打开 /dev/tty 以将输出发送到那里,并且您也会在其上发出 ioctl。当 less 打开 /dev/tty 时,这是与 shell 的标准输入的连接吗?
  • shell 的 fd 0 与子进程的 fd 0 相同,除非您重定向其输入。 /dev/tty 是进程的“控制终端”,所以大多数时候它等于 shell 的 fd 0,但是如果你将 fd 0 连接到一个文件(比如less .profile < /dev/null)你会看到less 仍然得到您的键盘输入,通过/dev/tty。但是,如果您将less 的输出重定向到不是tty 的东西(比如less .profile > /dev/null),它会注意到(使用isatty(1) 将尝试ioctl() 它)并且不会打开/dev/tty 并忽略标准输入为好吧。 (并且表现得像cat
  • strace 是你的朋友(在 linux 上) - 它显示所有系统调用,因此显示与“外部世界”相关的进程的所有操作。只需打开一个 shell 来进行 sttyless 实验,然后使用 strace -p PID -ff -o filename -s 10240 -v 或类似方法从另一个终端跟踪该 shell,这将为每个子进程生成一个名为 filename.PID 的单独输出文件。要查看进程的内部工作,请使用ltrace 或调试器。
猜你喜欢
  • 2023-03-28
  • 1970-01-01
  • 2015-07-07
  • 1970-01-01
  • 1970-01-01
  • 2015-10-09
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
相关资源
最近更新 更多