为什么while循环在被暂停后会停止?


10

为什么使用bash并暂停while循环,然后在恢复循环后停止循环?下面的简短示例。

$ while true; do echo .; sleep 1; done
.
.
^Z
[1]+  Stopped                 sleep 1
$ fg
sleep 1
$

我熟悉信号,我猜这可能是bash的自然行为,但我想更好地理解为什么它会以这种特定方式运行。


因为它必须处理中断并必须$?在返回时准确地反映出来,所以true不是true。大概。我认为。
mikeserv

1
我希望不要对此评论进行标记,但是我将用Unix koan式的另一个问题回答您的问题:“为什么学生在被停职后不再在操场上打架?” 答案是,因为他不再在有能力发动战斗的操场上了。因此,该行为已被简单地停止。
rubynorails 2015年

停止命令后,循环中断。然后,您将恢复单个sleep 1命令,而不是循环。
2015年

Answers:


10

这看起来像是几个shell中的错误,可以按预期与ksh93zsh一起工作

背景:

大多数shell似乎在主shell内运行while循环,

如果您使用非登录外壳输入^ Z,则Bourne Shell会挂起整个外壳

bash仅挂起the sleep,然后离开while循环,以便打印新的shell提示符

破折号使该命令不可悬浮

使用ksh93,事情就大不相同了:

在第一次启动命令时,ksh93会执行相同的操作,但与sleepksh93中的buitin一样,ksh93具有一个处理程序,该处理程序会导致while循环派生出主外壳,然后在您键入^ Z时挂起。

如果您稍后在ksh93中键入fg,则继续运行循环的派生子节点将继续。

比较bash和ksh93的jobcontrol消息时,您会看到主要区别:

bash报告:

[1]+ Stopped sleep 1

ksh93报告:

^Z[1] + Stopped while true; do echo .; sleep 1; done

zsh的行为类似于ksh93

对于这两个Shell,只要不键入^ Z,您就有一个进程(主shell),而在键入^ Z之后,您将拥有两个shell进程。


dash循环终止时,实际上没有处理信号吗?在[d]?ash源代码中,所有用于INTONINTOFF的散布在各处,通常在INTOFF状态下接收到的信号实际上是在INTON(或周围) 处理的。无论如何,我只是很好奇,因为我想您知道得更多-这是一个很好的答案。谢谢。
mikeserv

我很少使用破折号,最近我获取并编译了破折号,以便与bash,ksh93和我的Bourne Shell进行性能比较。在进行这些测试时,我发现破折号主要是快速的,因为它不包括对多字节字符的支持。sleep 100可以在中暂停和恢复单个文件dash,因此似乎dash了解此命令中的问题并有选择地禁用作业控制。
2015年

因此,在您的测试中,dash通过删除多字节处理,您是否能够在其他shell中实现与性能相同的性能?是的,dash它确实支持作业控制,但是该标准说交互式外壳程序应该忽略TSTP,并且在交互式终端上的当前外壳程序中运行while循环与其他外壳程序一样,都是交互式外壳程序。
mikeserv

我没有对此进行精确的测试,但是我可以看到虽然破折号比ksh93或Bourne Shell消耗更多的系统CPU时间(主要是因为它发出了更多的fork()调用),但它使用的用户CPU时间却更少,因此总消耗量相似与我的Bourne Shell版本相比,CPU时间。通过尝试减少Bourne Shell中的用户CPU时间,我知道大部分时间都花在了多字节转换上。
2015年

4

关于这个问题,我写了一位Bash的合著者,这是他的回复:

这不是一个真正的错误,但肯定是一个警告。

这里的想法是暂停进程,该进程与Shell命令的粒度单位不同。当进程被挂起时,它返回到外壳程序(状态为非零,当您停止一个作为循环测试的进程时会产生后果),它可以选择:它可以中断或继续循环,留下已停止的过程。当工作停止时,Bash选择-一直选择-跳出循环。继续循环很少是您想要的。

其他一些Shell会执行一些操作,例如,当某个进程由于SIGTSTP而被挂起时,派生该Shell的副本,并停止该进程。Bash从未做到过-似乎比收益保证书还复杂-但如果有人想以补丁形式提交该代码,我将考虑合并这些更改。

因此,如果有人想提交补丁,请使用手册页中找到的电子邮件地址。

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.