6

有没有办法阻止某些信号并取消阻止同一组中的其他信号?我只是似乎不明白它!

一个例子

sigset_t set;
sigemptyset(&set);

sigaddset(&set, SIGUSR1);
// Block signal SIGUSR1 in this thread
pthread_sigmask(SIG_BLOCK, &set, NULL);
sigaddset(&set, SIGALRM);
// Listen to signal SIGUSR2
pthread_sigmask(SIG_UNBLOCK, &set, NULL);


pthread_t printer_thread1, printer_thread2;
pthread_create(&printer_thread1, NULL, print, (void *)&f1);
pthread_create(&printer_thread2, NULL, print, (void *)&f2);

bool tl = true;
while(1)
{
    if(tl)
    {
        // thread1 does something
        kill(pid, SIGUSR1);
        // main thread waits for SIGALRM
        sigwait(&set, &sig);
        tl = !tl;
    }
    else
    {
        // thread2 does something
        kill(pid, SIGUSR2);
        // main thread waits for SIGALRM
        sigwait(&set, &sig);
        tl = !tl;
    }
}

我不允许只使用互斥锁、信号量等信号。

有人可以帮忙吗?:)

4

2 回答 2

11

有没有办法阻止某些信号并取消阻止同一组中的其他信号?

使用pthread_sigmask,您可以选择:

  • 使用常数将一组信号添加到一组阻塞信号中SIG_BLOCK
  • 使用常数将一组信号移到一组阻塞信号中SIG_UNBLOCK
  • 使用常量定义要阻塞的信号集SIG_SET

换句话说,线程当前有一组阻塞信号,您可以按照上面指定的方式修改它,一次一个操作。

重要的一点是,新创建的线程继承了创建线程的信号掩码,因此您可以在创建新线程之前设置新线程的掩码,或者在新线程将运行的函数中,在您方便时设置。

关于您的示例,我假设您正在尝试使用printer_thread1block SIGUSR2and SIGALRM,并且有printer_thread2block SIGUSR1and SIGALRM,并且有主线程 block SIGUSR1and SIGUSR2,这样每个线程都可以发送一个将被单个线程捕获的信号(没有代码printf1并且f2,不可能确定您在示例中的意图是什么)。

您应该能够通过以下代码实现这一点:

sigset_t set;
pthread_t printer_thread1, printer_thread2;


// Block signal SIGUSR1 & SIGALRM in printer_thread1
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
sigaddset(&set, SIGALRM);
pthread_sigmask(SIG_SET, &set, NULL);
pthread_create(&printer_thread1, NULL, print, (void *)&f1);

// Block signal SIGUSR2 & SIGALRM in printer_thread2
sigaddset(&set, SIGUSR2);
sigaddset(&set, SIGALRM);
pthread_sigmask(SIG_SET, &set, NULL);
pthread_create(&printer_thread2, NULL, print, (void *)&f2);

// Block signal SIGUSR1 & SIGUSR2 in the main thread
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
sigaddset(&set, SIGUSR2);
// Listen to signal SIGALRM
pthread_sigmask(SIG_SET, &set, NULL);


bool tl = true;
while(1)
{
    if(tl)
    {
        // thread1 does something
        kill(pid, SIGUSR1);
        // main thread waits for SIGALRM
        sigwait(&set, &sig);
        tl = !tl;
    }
    else
    {
        // thread2 does something
        kill(pid, SIGUSR2);
        // main thread waits for SIGALRM
        sigwait(&set, &sig);
        tl = !tl;
    }
}

请参阅这些手册页:

了解更多详情。

于 2012-10-29T01:46:05.933 回答
2

我想你想在这里做的是

// Block signal SIGUSR1 in this thread
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
pthread_sigmask(SIG_BLOCK, &set, NULL);

// Listen to signal SIGALRM
sigemptyset(&set);
sigaddset(&set, SIGALRM);
pthread_sigmask(SIG_UNBLOCK, &set, NULL);

该集合仅用于告诉它要阻止或取消阻止什么。一旦传递给命令,您就可以自由地重置它并建立另一个信号掩码。如果您跳过 sigemptyset,该集合仍将包含 SIGUSR1,随后将再次解除阻塞。好吧,我认为它至少是这样工作的——我已经很久没有使用信号了。

于 2012-10-29T01:17:00.470 回答