题 pause()如何工作?


我在c中完全是菜鸟。我必须写一个函数 mypause() 应具有类似于的功能 pause() 系统调用,并测试 mypause() 在重复阻止等待信号的程序中起作用。 te怎么样? pause() 功能工作?我不能只做一个 mypause() 喜欢这个:

fprintf( stderr, "press any key to continue\n" );

为了让程序阻止并等待信号?

请记住,我不能使用 pause() 要么 sigpause()


15
2018-04-13 20:30


起源


所以你想等一下击键? - m0skit0
听起来像是一个家庭作业问题。应该这样标记?无论如何,我认为你还不太了解你想要解决的问题。 pause()调用不等待用户输入。 - Andrew J. Brehm
即键盘事件不是这里所需的信号。 - Andrew J. Brehm
@ AndrewJ.Brehm我被告知家庭作业标签已经退役 - Dave
linux.die.net/man/2/pause  暂停等待信号(一种内核通信),而不是键盘输入。无论如何,fprintf根本不会暂停程序。 - FrankieTheKneeMan


答案:


pause() 功能块直到信号到达。用户输入不是信号。信号可以由另一个进程或系统本身发出。

紧迫 Ctrl-C 例如,导致你的shell发送一个 SIGINT 发信号到当前运行的进程,其中 正常 案件导致该过程被杀死。

为了模仿的行为 pause 在ISO C99中,您可以编写如下内容。代码已注释,如果您对此实现有疑问,请询问。

#include <unistd.h>
#include <stdio.h>
#include <signal.h>

/**
 * The type sig_atomic_t is used in C99 to guarantee
 * that a variable can be accessed/modified in an atomic way
 * in the case an interruption (reception of a signal for example) happens.
 */
static volatile sig_atomic_t done_waiting = 0;

static void     handler()
{
  printf("Signal caught\n");
  done_waiting = 1;
}

void    my_pause()
{
  /**
   *  In ISO C, the signal system call is used
   *  to call a specific handler when a specified
   *  signal is received by the current process.
   *  In POSIX.1, it is encouraged to use the sigaction APIs.
   **/
  signal(SIGINT, handler);
  done_waiting = 0;
  while ( !done_waiting )
    ;
}

int     main()
{
  my_pause();
  printf("Hey ! The first call to my_pause returned !\n");
  my_pause();
  printf("The second call to my_pause returned !\n");
  return (0);
}

请注意,此示例仅适用于 SIGINT 信号。要处理一组额外的信号,您可以使用其他来电 signal() 具有不同的信号编号或使用 sigaction() 用掩码引用所有想要的信号。

您可以在系统中找到系统中可用信号的完整列表 <signal.h> 包括。


13
2018-04-13 21:10



忙碌等待很糟糕。在那个循环中睡一觉。 - Dave
(睡觉会提前醒来发出信号) - Dave
感谢Halim Qarroum这正是我所需要的。 - Luis Quesado
@Dave你不能只使用睡眠,因为经典的竞争条件:当睡眠恢复时,你必须使用if语句来检查我们是否应该再次入睡。如果信号在那一刻到来,你就会被“塞满”。这正是sigsuspend被发明的原因。请参阅上面的评论:使用自管道的更聪明的信号处理程序是以无竞赛方式实现循环暂停的唯一其他方式(理智)。 - Nicholas Wilson
@Halim坚持你的枪;你的答案很好。忙碌的等待可能很难看,但在技术上是正确的,也许是你在ISO C中可以做到的最好而不会触及POSIX。尝试在循环中做一些奇特的事情是程序员犯错误的经典场所。 - Nicholas Wilson