2016-11-05 21 views
0

我正在尝试构建一个包含2/3线程的基本程序。主线程,信号线程和接收线程。我正在努力让主线程启动一个信号线和接收线程。然后信号线程应该向接收线程发送10个SIGUSR1信号并增加一个全局计数器。接收器线程应该接收10个信号,同时为每个接收到的信号增加自己的计数器。C和pthread_join拖延程序中的信号接收线程

我遇到的麻烦是在最后加入线程,特别是加入接收线程。如果我尝试将它们重新组合在一起,大部分时间程序都会停顿,我假设因为接收线程还没有完成它的工作(也许它错过了信号?),所以它永远不会结束。我想也许是这样,所以我在信号线程中引入了一个等待命令来减慢速度,但这并没有改变任何东西。

如果我注释掉pthread_join(receiver,NULL),程序将运行,但它大部分时间只捕获一个信号。我认为这是因为接收线程没有多少时间来运行。 (尽管它有时会捕获不同数量,取决于它被抢占的时间?)

离开程序中的pthread_join(接收器,NULL)使其失速19/20次,但程序返回10个信号的时间为1/20次发送和10收到。这使我相信它与抢先有关,但我不明白为什么它会摆在首位。

此外我现在只有接收器线程接收线程,而接收到的计数器是< 10.理想情况下,我只想将它留在while(1)循环中,但后来我不知道如何加入回到主线程中而不会冻结所有内容。

如果有人能帮我找出为什么信号错过/为什么程序冻结,我将非常感激。我怀疑我没有正确设置接收器的信号掩码,但我不知道我该怎么做。这里是代码:

#include <stdio.h> 
#include <pthread.h> 
#include <stdlib.h> 
#include <signal.h> 

void *receivetest(void *args); 
void *signaltest(void *args); 


int received = 0; 
int sent = 0; 
pthread_t signaler; 
pthread_t receiver; 
sigset_t mask; 

int main(){ 

    //setting up the signal mask 
    sigemptyset(&mask); 
    sigaddset(&mask, SIGUSR1); 

    //creation of both threads 
    pthread_create(&receiver, NULL, receivetest, NULL); 
    pthread_create(&signaler, NULL, signaltest, NULL); 


    pthread_join(signaler, NULL); 
    pthread_join(receiver, NULL); 

    //printing results after joining them back 
    printf("I'm the main function\n"); 
    printf("Receieved: %d, sent: %d\n", received, sent); 


} 

void *signaltest(void *args){ 
    int i = 0; 
    for(i=0;i<10;i++){ //sends 10 signals to receiver thread 
     pthread_kill(receiver, SIGUSR1); 
     sent++; 
    } 
} 

void *receivetest(void *args){ 
    int c; //sigwait needs int 
    pthread_sigmask(SIG_BLOCK, &mask, NULL); //sets up the signal mask for this thread 
    while(received < 10){ //waits for 10 signals and increments receieved 
     sigwait(&mask, &c); 
     received++; 
    } 
} 
+1

什么是你真正想干什么?你为什么试图将信号用作线程间通信机制? –

+0

'pthread_sigmask(SIG_BLOCK,&mask,NULL);'表示阻止'mask'中定义的所有信号。这应该被放置在主线程中,因此到达主线程的任何信号都将被传递给信号处理程序。这意味着信号接收器从不处理任何信号。它阻止了他们。 – alvits

回答

0

你几乎说得对。建议阻止来自主线程的信号,以防止所有新线程错误地处理信号。

pthread_sigmask()之后创建的任何线程都会继承sigmask。第一个参数告诉pthread_sigmask()如何处理第二个参数中列出的信号。

此行pthread_sigmask(SIG_BLOCK, &mask, NULL)应放置在主线程中,而不是放在信号处理程序中。您的原始代码也可以工作,但是如果信号发送到错误的线程,它将会终止整个过程。

另外,发送方发送信号的速度比接收方能够处理的要快。通过在每次迭代之间休眠1秒,接收器将能够赶上。

我冒昧地修改了你的代码。我在发件人和收件人中添加了一些打印件,以便您知道它在做什么。

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

void receivetest(void); //function does not return anything 
void signaltest(void); // does not accept parameter either. 


int received = 0; 
int sent = 0; 
pthread_t signaler; 
pthread_t receiver; 
sigset_t mask; 

int main(){ 

    //setting up the signal mask 
    sigemptyset(&mask); 
    sigaddset(&mask, SIGUSR1); 
    pthread_sigmask(SIG_BLOCK, &mask, NULL); //sets up the signal mask for this thread 

    //creation of both threads 
    pthread_create(&receiver, NULL, (void *)receivetest, NULL); 
    pthread_create(&signaler, NULL, (void *)signaltest, NULL); 


    pthread_join(signaler, NULL); 
    pthread_join(receiver, NULL); 

    //printing results after joining them back 
    printf("I'm the main function\n"); 
    printf("Receieved: %d, sent: %d\n", received, sent); 
    return 0; 

} 

void signaltest(void){ 
    int i = 0; 
    for(i=0;i<10;i++){ //sends 10 signals to receiver thread 
     printf("Sending signal\n"); 
     pthread_kill(receiver, SIGUSR1); 
     sleep(1); // Don't send signals too fast 
     sent++; 
    } 
} 

void receivetest(void){ 
    int c; //sigwait needs int 
    while(received < 10){ //waits for 10 signals and increments receieved 
     sigwait(&mask, &c); 
     printf("Signal received\n"); 
     received++; 
    } 
} 

输出:

Sending signal 
Signal received 
Sending signal 
Signal received 
Sending signal 
Signal received 
Sending signal 
Signal received 
Sending signal 
Signal received 
Sending signal 
Signal received 
Sending signal 
Signal received 
Sending signal 
Signal received 
Sending signal 
Signal received 
Sending signal 
Signal received 
I'm the main function 
Receieved: 10, sent: 10 
+0

我明白了,谢谢你。尽管如此,我仍然对设置sigmask感到困惑。为什么设置sigmask阻止掩码中的信号而不是打开它们?另外,如果我想要两个信号,我该怎么做?我是否在主功能中阻塞了两个信号,然后让receiver_a只等待一个信号,然后receiver_b只等待b信号?在那种情况下,sigwait的面具应该是什么? – bittersweets

+0

@bittersweets - 'pthread_sigmask'将做第一个参数告诉它做的事情。 'SIG_BLOCK'告诉它阻止第二个参数中列出的信号。在'pthread_sigmask()'后面创建的任何线程都会继承它。习惯上保护所有线程不受信号影响,并指定一个或多个线程来处理信号。 – alvits

+0

@bittersweets - 对于后续问题,每个信号处理程序都应该有自己的指定信号来等待。最好将'mask'定义为每个处理程序的局部变量。 – alvits

1

信号只是不这样工作。如果一个线程在这个信号已经挂起的时候收到一个信号,什么都不会发生。请使用适当的线程间通信方法,而不是信号。

+0

这是一个班级项目。我们被告知使用信号。 (该项目本身不同于我询问的程序,但它说使用信号发生器线程和信号处理程序线程)。 你认为程序冻结的原因是因为接收器丢失了发送给它的信号?我是否正确设置了信号掩模? – bittersweets

+0

在内部计数器达到10之前,您可能必须发送信号超过10次。信号不是一个事务性消息机制。 – sturcotte06

+0

谢谢。我已经尝试增加发送的数量,确实确实能够抓住它。 (虽然它仍然错过了很多..当发送100时,它仍然冻结了很大一部分时间。我想这就是为什么信号不好。通过使用信号灯我可以更好地同步它,但我不认为这就是我“M应该为项目做...) 不管怎么说,谢谢大卫·施瓦茨和sturcotte06 – bittersweets

相关问题