【问题标题】:Scanf with Signals带信号的扫描
【发布时间】:2011-01-31 13:19:18
【问题描述】:

我有一个阻止 SIGINT 的信号,基本上说“对不起,你不能退出。\n”

问题是这可能在 scanf 期间发生。

如果在 scanf 期间发生这种情况,scanf 会将 printf 作为输入。

我怎样才能做一个 printf 将导致 scanf 基本上自动按回车键。我不在乎我得到不好的输入。我只想用 printf 或其他东西以编程方式完成该 scanf。

流程:

scanf("得到东西") -> 用户可以输入内容。

-> SIGINT 发生并转到我的处理程序。

-> 处理程序对标准输出说“Blah blah blah”。

-> Scanf 已经接受了这个 blah blah blah 并且正在等待更多输入。

我如何做到这一点,以便在我返回 scanf 时完成(不管它收集了什么,我只是希望它在没有用户帮助的情况下继续运行)。

编辑:如果我发送两个信号,则 scanf 终止。我想以某种方式以编程方式模拟 scanf 的结尾。

【问题讨论】:

  • "如果在 scanf 期间发生这种情况,scanf 会将 printf 作为输入。"是一个奇怪的说法,你是这个意思吗?你玩过你没有解释过的文件描述符或管道吗?在正常的 C 启动中,stdin 和 stdout 是相当分离的。
  • 我不确定它是否进入scanf,但如果我之后将数据输入scanf,它永远不会工作。我根本不希望它回到 scanf 语句,这就是我的问题。

标签: c++ unix signals scanf qnx


【解决方案1】:

您的问题表明您很困惑 - 或者英语不是您的母语。

我有一个阻止 SIGINT 的信号,基本上说“对不起,你不能退出。\n”

您可能拥有一个设置为响应 SIGINT 的信号处理程序。此外,您可能正在使用 'signal()' 函数来设置处理程序 - 但您应该旨在使用 POSIX 标准 'sigaction()' 函数来设置处理程序。

问题是这可能在 scanf 期间发生。

在上下文中,“this”可能是一个中断信号,由希望停止程序的用户键入。小心使用中断信号阻止人们退出程序;如果你不让他们那样做,他们会更加残暴。这可能意味着他们将生成 SIGQUIT (可能还有核心转储);如果你也阻止它,他们可以尝试许多其他技巧,直到他们达到最终的“kill -9 pid”,你的程序将没有机会做出反应。

如果在 scanf 期间发生这种情况,scanf 会将 printf 作为输入。

这很混乱...您可能是在暗示“printf()”语句的输出(可能是“您不能退出”的语句)然后被视为“scanf()”的输入'?这似乎不太可能......这需要对进程的 I/O 进行非常非常奇怪的设置,我仍然不相信它会发生。

我怎样才能做一个 printf 将导致 scanf 基本上自动按回车键。我不在乎我得到不好的输入。我只想用 printf 或其他东西以编程方式完成该 scanf。

有几种可能性 - 部分取决于您使用的操作系统(即使它是 POSIX。)我不使用 'scanf()';我觉得太难控制了。如果您的系统在中断处理程序返回后恢复读取,那么您将遇到困难。但有时,'scanf()' 会停止并返回它已处理的项目数。如果你的'scanf()'没有终止,那么你需要考虑在一个简单地调用'setjmp()'的函数中插入一个'sigsetjmp()',然后调用你调用'scanf()'的函数.然后您的信号处理程序可以使用“siglongjmp()”返回到该中间函数:

sigjmp_buf trap;

int intermediary(int argument)
{
    if (sigsetjmp(trap) == 0)
    {
         function_calling_scanf(argument);
         return 0;  // Success
    }
    // Report failure
    return -1;
}

您的描述继续:

流程:

   scanf("get stuff") -> User is able to enter stuff in.

-> SIGINT 发生并转到我的处理程序。

-> 处理程序对标准输出说“Blah blah blah”。

-> Scanf 已经接受了这个 blah blah blah 并且正在等待更多输入。

你怎么知道 scanf 已经读过'blah blah blah'?这对我来说似乎非常非常不可能。

我如何做到这一点,以便在我返回 scanf 时完成(不管它收集了什么,我只是希望它在没有用户帮助的情况下继续运行)。

使用sigsetjmp()

编辑:如果我发送两个信号,则 scanf 终止。我想以某种方式以编程方式模拟 scanf 的结尾。

这表明您正在使用“signal()”来设置信号处理程序,而不是“sigaction()”。使用“signal()”,当中断发生时,信号处理程序被设置回默认值。使用“sigaction()”,您必须请求该行为;默认情况下,接收到的信号 (SIGINT) 在持续时间内被阻塞,并且信号处理程序保持有效。如果在第一个中断运行时发生第二个中断,则第二个中断会一直保持到第一个处理程序返回(此时处理程序将重新进入)。

【讨论】:

  • 感谢您的努力。我很抱歉。已经很晚了,我试图回答我的问题。我通过删除 scanf 并使用 fgets 解决了这个问题。
【解决方案2】:

不要使用 scanf,因为它的缓冲或重试代码可能会妨碍。如果您使用read(2) 调用,它应该返回-1 并带有EINTR 的errno。 Scanf 可能会看到该错误并重试读取。您始终可以从原始读取中扫描数据。

这是假设 QNX 是 POSIX 兼容的读取,并且您没有用于检查的 scanf 源。

【讨论】:

  • 问题是我正在使用我没有选择使用的功能。它符合 POSIX。
  • 你走在了正确的轨道上。我再也不会使用 scanf 了。除了我使用 fgets 之外,我不得不沿用这条线。
  • 不使用 scanf() 是个好主意;根据我的经验,使用 fgets() 更为明智。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-05
  • 1970-01-01
  • 2013-09-24
相关资源
最近更新 更多