gpt4 book ai didi

C + UNIX,siglongjmp 和 sigsetjmp

转载 作者:可可西里 更新时间:2023-11-01 11:49:21 28 4
gpt4 key购买 nike

我有一本(较旧的)教科书中的程序,旨在说明 POSIX 信号在 UNIX 上的使用。该程序运行一个计算循环,从固定点开始计算完美数。

  • 时间警报信号用于定期打印状态。
  • 中断信号用于按需状态。
  • 退出信号用于重置测试间隔(或终止)。

void perfect(int);

sigjmp_buf jmpenv; /* environment saved by setjmp*/

int n; /* global variable indicating current test point */

int main() {

int begin; /* starting point for next search*/
/* interrupt routines*/
void status();
void query();

sigset_t mask;
struct sigaction action;


if (sigsetjmp(jmpenv,0)) {
printf("Enter search starting point (0 to terminate): ");
scanf("%d",&begin);
if (begin==0) exit(0);
sigprocmask(SIG_UNBLOCK, &mask, NULL);
}
else begin=2;

/* Status Routine will handle timer and INTR */

sigemptyset(&mask);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGALRM);
sigaddset(&mask, SIGQUIT);
action.sa_flags=0;
action.sa_mask=mask;

action.sa_handler=status;
sigaction(SIGINT,&action,NULL);
sigaction(SIGALRM,&action,NULL);

action.sa_handler=query;
sigaction(SIGQUIT,&action,NULL);

/* start alarm clock */
alarm(20);
perfect(begin);
}

void perfect(start)
int start;
{
int i,sum;

n=start;

while (1) {
sum=1;
for (i=2;i<n;i++)
if (!(n%i)) sum+=i;

if (sum==n) printf("%d is perfect\n",n);
n++;
}
}

void status(signum)
int signum;
{

alarm(0); /* shutoff alarm */

if (signum == SIGINT) printf("Interrupt ");
if (signum == SIGALRM) printf("Timer ");

printf("processing %d\n",n);

alarm(20); /*restart alarm*/
}

void query() {siglongjmp(jmpenv,1);}

我的问题是:

  1. 为什么调用void status();和无效查询();一开始主要是?
  2. 在 if 语句检查 begin == 0 并决定退出后,它遵循名为“sigprocmask(SIG_UNBLOCK, &mask, NULL);”的一行为什么我必须在退出后解锁它?

最佳答案

  1. 这两行将函数 status()query() 声明为返回 void。他们没有具体说明他们采用什么论据。在现代 C 中,在另一个函数中声明函数是令人厌恶的(并且在没有完整原型(prototype)的情况下声明它们也是令人厌恶的——但这似乎是另一天的讨论,因为它不是你的代码)。函数应该在其他函数之外声明,如果它们在另一个文件中定义或使用,它们应该在头文件中声明。如果它们在当前文件中定义并且未在任何其他文件中使用,则应将它们声明并定义为 static 函数。

  2. 变量 begin 被非正统地初始化。在第一次通过代码时将其设置为 2;从 sigsetjmp() 返回非零后,它由用户输入设置。它也可能被 setjmp() 东西破坏,因为它没有被标记为 volatile。规则很深奥。

    但是,其意图是如果 begin 为零,则程序退出。否则,它将继续。 sigprocmask() 旨在解锁任何被屏蔽的信号。我不清楚是否有必要。当您从信号处理程序返回时,被阻塞的信号应该被解除阻塞——我认为——即使您通过 siglongjmp() 退出也是如此。

请注意,在信号处理程序中调用 printf() 会调用未定义的行为。很可能会没事,但不能保证。在 POSIX standard 中有一个可以调用的函数列表。或关于 SO 的其他问题(我知道我之前已经给出了该列表)。


仔细阅读函数的手册页:

Chris Dodd当他 comments 时是正确的第二个参数为 0 的 sigsetjmp() 不会保存当前信号掩码。注意mask的值是在setjmp()调用后修改的局部变量中,没有标记volatile,所以它的值当 setjmp() 返回非零值时不确定(请参阅 setjmp() 手册页中的注意事项)。

sigsetjmp() 手册页的基本原理部分读起来很有趣,并提到了 4.2 BSD(1982 年发布)中出现的类似功能,因此我对它们在 70 年代不存在的评论仍然有效(K&R 第一版和第七版 UNIX™ 分别于 1978 年和 1979 年发布)。 sig* 名称是 AFAICT,由 POSIX 发明(BSD 系统包括 _setjmp()_longjmp())。

关于C + UNIX,siglongjmp 和 sigsetjmp,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20647808/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com