如何使用sigsuspend

Lui*_*ado 5 c

我有这个代码,我必须让程序块反复等待信号.我的老师希望我们使用sigsuspend和面具而不是暂停或睡眠.我不熟悉的sigsuspend或面罩,我知道,sigsuspend()临时替换用面膜给出的面具调用进程的信号屏蔽,然后挂起过程,直到传递的信号,其作用是调用信号处理程序或终止进程.但是我该如何实现呢.

#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

unsigned Conta = 0;

void mypause(int sign)
{
    switch (sign)
    {
        case SIGINT:
            printf("You've pressed ctrl-C\n");
            printf("I'm running waiting for a signal...\n");
            Conta++;
            break;

        case SIGQUIT:
            printf("You've pressd ctrl-\\n");
            printf("Number of times you've pressed CTRL-C: %d", Conta); 
            exit(0);
            break;
    }
}

int main()
{
    alarm(3);
    printf("I'm Alive\n");

    signal(SIGINT, mypause);
    signal(SIGQUIT, mypause);
    printf("I'm running, waiting for a signal...\n");
    while (1)
    {
    }

    return (0);
}
Run Code Online (Sandbox Code Playgroud)

Ark*_*kku 8

开始的简单方法是sigsuspend使用空掩码调用(即,任何信号都可以唤醒程序):

sigset_t myset;
(void) sigemptyset(&myset);
while (1) {
    (void) printf("I'm running, waiting for a signal...\n");
    (void) sigsuspend(&myset);
}
Run Code Online (Sandbox Code Playgroud)

下一步是用来sigprocmask禁用你的两个处理信号(SIGINTSIGQUIT),而不是在你等待它们时sigsuspend.然后你会使用sigprocmask悬挂时从空掩码中获取的"旧掩码" .


Mat*_*ips 7

libc中手动GNU描述似乎很清楚和透彻:

功能:int sigsuspend(const sigset_t*set)

此函数用set替换进程的信号掩码,然后暂停进程,直到传递一个信号,其动作是终止进程或调用信号处理函数.换句话说,程序被有效地暂停,直到其中一个非集合成员的信号到达.

如果通过传递调用处理函数的信号唤醒进程,并且处理函数返回,则sigsuspend也会返回.

只要sigsuspend正在等待,掩码就会保持设置.函数sigsuspend在返回时始终恢复先前的信号掩码.

返回值和错误条件与暂停相同.

使用sigsuspend,您可以使用完全可靠的内容替换上一节中的暂停或睡眠循环:

 sigset_t mask, oldmask;

 ...

 /* Set up the mask of signals to temporarily block. */
 sigemptyset (&mask);
 sigaddset (&mask, SIGUSR1);

 ...

 /* Wait for a signal to arrive. */
 sigprocmask (SIG_BLOCK, &mask, &oldmask);
 while (!usr_interrupt)
   sigsuspend (&oldmask);
 sigprocmask (SIG_UNBLOCK, &mask, NULL);
Run Code Online (Sandbox Code Playgroud)

最后一段代码有点棘手.这里要记住的关键点是,当sigsuspend返回时,它会将进程的信号掩码重置为原始值,即调用sigsuspend之前的值 - 在这种情况下,SIGUSR1信号再次被阻止.第二次调用sigprocmask是明确解除阻塞此信号所必需的.

另外一点:你可能想知道为什么while循环是必要的,因为程序显然只等待一个SIGUSR1信号.答案是传递给sigsuspend的掩码允许通过传递其他类型的信号唤醒进程,例如作业控制信号.如果该过程被一个未设置usr_interrupt的信号唤醒,它只会再次暂停,直到"正确"的信号最终到达.

这种技术需要更多的准备工作,但对于您想要使用的每种等待标准,只需要一次.实际等待的代码只有四行.