为什么 ed 不能用 Cc 退出?

为什么 ed 不能用 Cc 退出?

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

$ ed
hello
?
help
?
exit
?
quit
?
^C
?
^C
?
?
?
^D
$ su
# rm -f /bin/ed

这种悲惨的浪费是很容易避免的,只要ed同意被打断即可。

另一个表现出类似行为的顽固程序less似乎也没有太多理由被忽视C-c。为什么这些程序不直接接受提示呢?

答案1

Ctrl+C发送信号情报。 SIGINT 的常规操作是返回到程序的顶层循环,取消当前命令并进入程序等待下一个命令的模式。只有非交互式程序才会因 SIGINT 而终止。

因此,Ctrl+很自然C不会杀死 ed,而是使其返回到其顶层循环。Ctrl+C中止当前输入行并返回到 ed 提示符。

less 也是如此:Ctrl+C中断当前命令并将您带回到命令提示符。

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

答案2

Unix V7ed(1)源代码是一个原始的 1,762 行 C 程序,只有几条注释,其中之一就是这个极具启发性的头注释:

/*
 * Editor
 */

鉴于源代码本身不提供任何基本原理,您只能从程序的作者那里获取它。

ed最初写的是作者:Ken Thompson 在 PDP-11 组装中,但它被移植到C丹尼斯·里奇,他为 Unix 创建了 C,然后用它使 Unix 可移植到非 PDP 机器。唉,里奇博士不再回答这些问题了。

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

以下是ed的作用Ctrl-C

onintr()
{
    signal(SIGINT, onintr);
    putchr('\n');
    lastc = '\n';
    error(Q);
}

(是的,凯瑞C。我们不需要返回类型说明符或参数声明。)

翻译成英文ed

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

  2. 写出一个新行并记住它是通过全局变量²执行的lastc

  3. 调用该error()函数,其中著名地?从用户的角度来看,它的作用只不过是 print 。

换句话说,它是在说:“你并不是真的想这么做,是吗?”


脚注:

  1. Unix 没有收到自动重置信号直到 4.3BSD,于 20 世纪 80 年代中期发布。请参阅“与其他系统的比较”下的第一个要点。

  2. ed.c有大约六十全局变量!

答案3

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

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

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

答案4

ed需要关心三个信号:

  1. INT
  2. HUP
  3. QUIT

POSIX 规范ed关于这些说如下:

SIGINT

ed实用程序应中断其当前活动,将字符串写入?\n标准输出,然后返回命令模式(请参阅扩展描述部分)。

SIGHUP

如果缓冲区不为空并且自上次写入以来已发生更改,则ed实用程序应尝试将缓冲区的副本写入文件中。首先,ed.hup应使用当前目录中命名的文件;如果失败,则应使用环境变量ed.hup指定的目录中指定的文件。HOME在任何情况下,ed实用程序都应退出,而不将文件写入当前记住的路径名,也不返回到命令模式。

SIGQUIT

实用ed程序应忽略此事件。

因此,无论您使用什么实现ed,它都符合 POSIX 关于INT信号(即Ctrl+C发送的内容)的规范。

在这方面,编辑器的行为就像一个交互式 shell,它也不会在收到信号后终止INT。其他编辑器,如vi和 也nano做同样的事情。

相关内容