【问题标题】:How to read Ctrl+C as input如何读取 Ctrl+C 作为输入
【发布时间】:2022-01-01 21:58:00
【问题描述】:

(在 Linux 中)

我找到的方法都使用signal。

没有别的办法了吗?有什么办法可以让终端将其放入输入缓冲区?

【问题讨论】:

  • 使用signal 是正确的方法。为什么你不能使用它?这并不难。
  • 不,没有。另请参阅What is the XY problem?
  • @Bib 因为我觉得好像很麻烦
  • 不麻烦。这非常容易。它只需要几行。记住,你边做边学。
  • 您可以尝试将终端置于原始模式,如下所述:stackoverflow.com/a/4217250/2485966

标签: c++ c linux terminal


【解决方案1】:

为了“读取 CTL+C 作为输入”而不是让它生成 SIGINT,to use tcsetattr() 需要清除 cc_c[VINTR] 或清除 ISIG 标志,如我在我的手册页中所述链接到这里。

您需要使用tcgetattr,首先,读取当前终端设置,进行相应调整,然后使用tcsetattr 进行设置。

您应该确保在程序终止时将终端设置重置为其原始默认值,这并不是说 shell 会为您将它们重置为默认值。

【讨论】:

  • 虽然这是真的,但它不太可能为 OP 服务。尽管要求将 control-C 作为一个字符来阅读,但这可能对他们没有多大好处。尤其是其本身——一旦这些标志被清除,控制-C 组合键发送什么字符,并且在给定其他默认设置的情况下,它是否会导致发送缓冲区或是否需要进行其他更改以导致发送字符立即地? (因为,如果不立即发送,用户将按下 control-C 并期待程序立即响应,但程序仍将等待输入。)
  • 也许,@EricPostpischil,OP 想要重新实现 emacs,其中 ^C 是一个有效的键盘命令,或者是其中的一部分,从标准输入读取它并相应地对其进行操作没有任何问题.在任何情况下,一旦 ^C 变得像普通字符一样可读,阅读 ^C 是否有用将根据其自身的优点进行评估。即使事实证明不是这样,所提出的原始问题也是一个完全合理、有效的问题,其答案准确地解决了所提出的问题。
  • 你不需要这样做。当输入来自 tty 时,这将使您的程序以不同的方式处理,而 ttty 有一个转义字符用于此目的。阅读我的答案,了解根本不需要编程的解决方案。
【解决方案2】:

不,signal() 不是办法。您应该需要配置tty 驱动程序来执行原始输入(驱动程序中没有输入字符处理),因此它会传递所有字符而不受影响。但这需要将tty 输入设备视为特殊设备并编写特殊代码来处理这种情况(这需要您发出多个ioctl 系统调用)。但不建议这样做,原因如下所述。

其次,还有另一种更简单的方法,不需要使用原始模式。您可以通过在tty 前面添加转义字符转义 Ctrl-C 字符。 在Linux 和BSD 系统中,这通常与Ctrl-V 字符相关联,因此按Ctrl-V + Ctrl-C 允许您输入单个 Ctrl-C 字符。我刚刚用hd 命令检查了它:

$ hd
^C
00000000 : 03 0a                                           : ..
00000002
$ _

接下来的问题是,如何输入Ctrl-V?好吧,就加倍吧! (但我们现在超出了范围,请继续阅读)

这种方法的优点是它不需要在您的程序中进行编程,并且在从文件、管道、fifo、套接字等读取时将以相同的方式工作(Ctrl-C 对此没有特殊含义,因为tty 驱动程序不在现场)在检测到Ctrl-C 时产生中断的唯一设备是tty 驱动程序(更准确地说,控制tty,在它的代码通用部分,所以所有tty s 这样做)并且它还有一个转义字符(出于同样的原因,所有ttys 都有它)来使下一个字符的特殊含义无效。

您可以使用stty(1) 命令检查哪个字符是转义字符,该命令配置为lnext 条目。但我几乎可以向你保证,它会是 Ctrl-V。

注意

这也适用于终端用于特殊目的的任何其他特殊字符(如 Ctrl-D、Ctrl-H 等)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-11
    • 2014-10-15
    • 1970-01-01
    • 2014-05-20
    • 2013-04-06
    • 2021-04-12
    • 1970-01-01
    相关资源
    最近更新 更多