为什么不能用 Cc 退出 ed?

Lil*_*ung 23 less interrupt ed

该程序ed是一个最小的文本编辑器,不能通过使用Ctrl-向它发送中断来退出C,而是打印错误消息“?” 到控制台。为什么ed在收到中断时不直接退出?当然,没有理由为什么一个神秘的错误消息在这里比退出更有用。这种行为导致许多新用户进入以下类型的交互:

$ ed
hello
?
help
?
exit
?
quit
?
^C
?
^C
?
?
?
^D
$ su
# rm -f /bin/ed
Run Code Online (Sandbox Code Playgroud)

如此悲惨的浪费——如果ed只是同意被打断,就很容易避免。

另一个表现出类似行为的顽固程序less似乎也没有太多理由忽略C-c. 为什么这些程序不只是提示?

Gil*_*il' 22

Ctrl+C发送SIGINT。SIGINT 的常规操作是返回程序的顶级循环,取消当前命令并进入程序等待下一个命令的模式。只有非交互式程序应该死于 SIGINT。

所以很自然地Ctrl+C不会杀死 ed,而是导致它返回到它的顶级循环。Ctrl+C中止当前输入行并返回到 ed 提示。

更少的情况也是如此:Ctrl+C中断当前命令并将您带回其命令提示符。

由于历史原因,ed 忽略了SIGQUIT ( Ctrl+ \)。正常的应用程序不应捕获此信号并允许自己终止,如果启用则使用核心转储。


War*_*ung 18

Unix的V7ed(1)源代码是只需几个注释,其中之一是该高度启发头注释原始的1762行的C程序:

/*
 * Editor
 */
Run Code Online (Sandbox Code Playgroud)

鉴于源代码本身没有提供任何理由,您只能从程序作者那里获得它。

ed最初由 Ken Thompson 在 PDP-11 汇编中编写,但您实际上需要与将其移植到 C 的人交谈。那可能是Dennis Ritchie,因为他为 Unix 创建了 C,并且是许多使用 C 的人之一使 Unix 可移植到非 PDP 机器上。不过,里奇博士不再回答这些问题了。

我对代码的阅读表明,这样做是为了尝试保留已编辑文档的核心副本的内容。您会注意到其他文本编辑器也不会死在Ctrl-C.

这是在ed做什么Ctrl-C

onintr()
{
    signal(SIGINT, onintr);
    putchr('\n');
    lastc = '\n';
    error(Q);
}
Run Code Online (Sandbox Code Playgroud)

(是的,K&R C。我们不需要 steenkin' 返回类型说明符或参数声明。)

翻译成英文,ed

  1. 重新注册信号处理程序。

    (Unix直到1980 年代中期的4.3BSD才获得自动重置信号。)

  2. 写出一个新行,并通过全局变量记住它这样做了lastc

    ed.c有大约60 个全局变量。)

  3. 从用户的角度调用该error()函数,众所周知,该函数所做的只是 print ?

换句话说,它是在说,“你不是真的想那样做,是吗?”

  • @derobert Vi 以 Unix 方式对待 Ctrl+C:回到顶层。由于其非 Unix 起源,Emacs 有自己的键绑定;Unix 的 Ctrl+C 的 Emacs 等价物是 Ctrl+G(响铃字符 - 在计算机上按响铃以中断它) (3认同)
  • 另外值得注意的是,很多文本编辑器不会在 Control-C 上退出。Vim 也没有。纳米也不行。我认为 emacs 也没有,但没有安装它进行测试。 (2认同)
  • @Gilles:在 `ed.c` 中调用 `error(s)` 的副作用之一是返回到主处理循环。它通过一个 `longjmp()` 调用来实现。*不寒而栗* (2认同)
  • 感谢您提供详细信息和历史课。这是一本很棒的书! (2认同)

Vol*_*gel 7

ed和其他交互式程序一样,使用Ctrl+C来中断程序本身的任务。
这与正常情况非常相似,它会中断在 shell 中运行的任务 - 命令。

从用户的角度来看,这两种变体非常相似。信号的处理不同:通常情况下,信号SIGINT发送到前台进程,一个运行的命令,命令通过退出来处理它。
在 的情况下ed,信号被发送到前台进程,即ed实例。如果有任务在运行ed,则中断并显示提示。如果没有正在运行的任务,则没有任何更改。

请注意,shell 也不会在Ctrl+ 上退出C,就像ed. 并且它确实在Ctrl+上退出D。再次,就像ed