为什么ED无法通过Cc退出?


20

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

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

这样的悲剧性浪费—如果ed简单地同意被打断就很容易避免。

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


4
交互式应用程序与非交互式应用程序不同。您习惯的Ctrl-C行为是非交互行为的默认行为。出于自身目的,交互式控件可能会覆盖Ctrl-C的行为。
jw013

4
另外,不确定笑话
jw013 2014年

@ jw013是的,“典型会议”是个玩笑(由于某种原因我找不到那个),但是我的问题很严重。我不明白的是,为什么这些应用程序选择覆盖Ctrl-C的行为(如果它实际上没有提供任何有用的信息)。
莉莉·钟

1
由于此问题是“如何退出ed”的谷歌搜索的最佳答案,因此我想在这里补充一下,它只是一个“ q”,后面是一个返回。许多博恩人死了,以带给我们这些信息。
德米特里

Answers:


19

Ctrl+ C发送SIGINT。SIGINT的常规操作是返回程序的顶级循环,取消当前命令并进入一种模式,在该模式下程序等待下一条命令。只有非交互式程序才能从SIGINT中消失。

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

花费更少的钱也一样:Ctrl+ C中断当前命令,并使您返回其命令提示符。

由于历史原因,ed忽略了SIGQUITCtrl+ \)。普通应用程序不应捕获此信号,并允许自己终止,并启用核心转储。


@Kzqai没有,正常的应用程序应该赶SIGQUIT,它的目的是作为一个应急出口。
吉尔斯(Gillles)“所以-别再邪恶了”,

啊,知道了 好吧,退缩了。
Kzqai

18

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

/*
 * Editor
 */

鉴于源代码本身不提供任何依据,您只能从该程序的作者处获取它。

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

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

下面是ed做的Ctrl-C

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

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

翻译成英文ed

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

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

  2. 写出新行,并记住它是通过global变量完成的lastc

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

  3. 调用error()函数,它著名的做多一点的打印?,从用户的角度来看。

换句话说,这是在说:“您不是真的要这么做吗?”


2
同样值得注意的是,许多文本编辑器不会在Control-C上退出。Vim也没有。纳米也没有。我也不认为emacs可以,但是也没有安装它进行测试。
derobert

3
@derobert Vi以Unix方式对待Ctrl + C:回到顶层。由于其非Unix起源,Emacs具有自己的键绑定。与Unix的Ctrl + C等效的Emacs是Ctrl + G(铃铛字符—在计算机上按铃以打断它)
吉尔斯'SO-不再是邪恶的'

@derobert:公平点。我已将此添加到答案中。
沃伦·杨

2
@Gilles:一个调用的副作用error(s)ed.c是返回到主处理循环。它通过longjmp()电话进行。颤抖
沃伦·杨

1
感谢您提供详细信息和历史课程。这是一本很棒的书!
alichaudry

7

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

从用户的角度来看,这两种变体非常相似。信号的处理不同:在通常情况下,信号SIGINT被发送到前台进程(正在运行的命令),然后该命令通过退出对其进行处理。
在的情况下ed,信号被发送到前台进程(ed实例)。如果有正在运行的任务ed,该任务将被中断并显示提示。如果没有任务在运行,则什么都不会改变。

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


3

有三个信号ed在乎:

  1. INT
  2. HUP
  3. QUIT

POSIX规范ed对此有以下说明:

SIGINT

ed实用程序将中断其当前活动,写入字符串?\n到标准输出,并返回到命令模式(请参阅补充说明部分)。

SIGHUP

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

SIGQUIT

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

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

在这方面,编辑器的行为就像一个交互式外壳,它在接收到INT信号后也不会终止。其他编辑器(例如vi和)nano执行相同的操作。


1
一些程序实现故意与POSIX相抵触,因此在这种情况下解释该标准的原理/破坏它的成本可能很有用。stackoverflow.com/questions/38605463/…–
sourcejedi

1
@sourcejedi该标准在其基本原理中未提及任何信号。我没有发现任何理由说明我在现有资料中为何遵循该标准ed。它的行为与外壳类似,外壳在接收INT信号时也不会终止。
库沙兰丹
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.