C pthread之间的信号处理

C pthread之间的信号处理,c,multithreading,pthreads,signals,signal-handling,C,Multithreading,Pthreads,Signals,Signal Handling,我试图学习进程和线程之间的信号处理。回答几个问题会帮助我更好地理解它 我知道一个进程可以向进程组发送信号,并允许多个进程接收相同的信号,但我不确定线程 多个pthread能否同时处理发送到所有pthread的信号 我将程序设置为使用阻止所有信号,我有两个线程用于等待信号,我让主线程发送SIGUSR1信号。当只有一个线程处理信号时(我在另一个线程中注释掉代码),似乎一切都很好,但是当两个线程都运行sigwait()代码时,它挂起或终止得太快 代码粘贴在下面 sig_atomic_t signa

我试图学习进程和线程之间的信号处理。回答几个问题会帮助我更好地理解它

我知道一个进程可以向进程组发送信号,并允许多个进程接收相同的信号,但我不确定线程

  • 多个pthread能否同时处理发送到所有pthread的信号
我将程序设置为使用阻止所有信号,我有两个线程用于等待信号,我让主线程发送SIGUSR1信号。当只有一个线程处理信号时(我在另一个线程中注释掉代码),似乎一切都很好,但是当两个线程都运行
sigwait()
代码时,它挂起或终止得太快

代码粘贴在下面

sig_atomic_t signals = 0;
sig_atomic_t sigusr1_signals = 0;
sig_atomic_t sigusr2_signals = 0;
sig_atomic_t count = 0;
sig_atomic_t totalcount = 0;

sigset_t globalset;

int WAIT = 1;           /* false = 0, true = 1 */

static int SIGNALS_SENT = 0;
static int SIGNALS_RECEIVED = 0;

void *sig1handler1(void *argv);

void *reporterhandler(void *argv);

int random_number(int min, int max);

int main(void) {

    pthread_t threads[2];   /* create an array to store a number of threads */

    //int *p_status = &status;
    sigfillset(&globalset);
    pthread_sigmask(SIG_BLOCK, &globalset, NULL);

    /* Generate signal handling threads */
    if (pthread_create(&threads[0], NULL, &sig1handler1, NULL) > 0)
    {
        printf("Thread creation failure!\n");
        return -1;
    }


    /* create reporting thread */
    if (pthread_create(&threads[1], NULL, &reporterhandler, NULL) > 0)
    {
        printf("Thread creation failure!\n");
        return -1;
    }

    /* Signal all threads to begin work concurrently */
    WAIT = 0;

    int c = 0;
    while(c < 100)
    {
        int value = random_number(1, 2);
        if (value == 1)
            kill(0, SIGUSR1);
        else
            kill(0, SIGUSR2);

        SIGNALS_SENT++;
        c++;
        usleep(10000);
    }

    kill(0, SIGINT);


    /* Wait for each thread to finish and join */
    int i = 0;
    for(i = 0; i < 2; i++)
    {
        if (pthread_join(threads[i], NULL) > 0)
        {
            printf("Thread [%u] join failure!\n", (unsigned int)threads[i]);
            return -1;
        }

        printf("THREAD [%u] returned.\n", (unsigned int)threads[i]);
    }

    printf("Parent Process [%d] exiting successfully.\n", getpid());
    return EXIT_SUCCESS;
}


void *sig1handler1(void *argv)
{
    pthread_t tid = pthread_self();
    printf("THREAD[%u] sig1handler1: waiting for signal to do some work...\n", (unsigned int)tid);

//  sigset_t myset;
//  sigfillset(&myset);
//  sigdelset(&myset, SIGINT);
//  sigdelset(&myset, SIGUSR1);
//  pthread_sigmask(SIG_SETMASK, &myset, NULL);

    /* Wait for a signal to start work */
    while (WAIT);

    int sig;
    int count = 0;

    while(1)
    {
        sigwait(&globalset, &sig);
        if (sig == SIGUSR1)
        {
            sigusr1_signals++;
            signals++;
            count++;
            //printf("thread1: caught SIGUSR1 signal!\n");
        }
        else if (sig == SIGINT)
        {
            printf("thread1: caught SIGINT signal, detected SIGUSR1 %d times, and terminating!\n", count);          pthread_exit(NULL);
        }
    }

    //printf("THREAD[%u] sig1handler1: doing some work!\n", (unsigned int)tid);
    //return (void *)EXIT_SUCCESS;
    //return (void *)NULL;
    pthread_exit(NULL);
}

void *reporterhandler(void *argv)
{
    pthread_t tid = pthread_self();
    printf("THREAD[%u] reporter: waiting for signal to do some work...\n", (unsigned int)tid);

    int sig;
    int count = 0;

//  sigset_t myset;
//  sigfillset(&myset);
//  sigdelset(&myset, SIGINT);
//  sigdelset(&myset, SIGUSR1);
//  sigdelset(&myset, SIGUSR2);
//  pthread_sigmask(SIG_SETMASK, &myset, NULL);

    /* Wait for a signal to start work */
    while (WAIT);

    while(1)
    {
        sigwait(&globalset, &sig);
        if (sig == SIGUSR1)
        {
            sigusr1_signals++;
            signals++;
            count++;
            totalcount++;
            SIGNALS_RECEIVED++;
        }
        else if (sig == SIGUSR2)
        {
            sigusr2_signals++;
            signals++;
            count++;
            totalcount++;
            SIGNALS_RECEIVED++;
        }
        else if (sig == SIGINT)
        {
            printf("Reporter: SIGUSR1 detected %d times\n", sigusr1_signals);
            printf("Reporter: SIGUSR2 detected %d times\n", sigusr2_signals);
            printf("Reporter: detected %d signals\n", totalcount);
            printf("Reporter: SIGNALS_SENT %d \n", SIGNALS_SENT);
            printf("Reporter: SIGNALS_REC %d \n", SIGNALS_RECEIVED);
            pthread_exit(NULL);
        }

        /* Display Report after detecting 10 signals */
        if (count == 10)
                    sigusr1_signals, sigusr2_signals);

            count = 0;
        }
    }

    //printf("THREAD[%u] reporter: doing some work!\n", (unsigned int)tid);
    pthread_exit(NULL);
}

int random_number(int min, int max)
{
    if (min < max)
    {
        max = max + 1;      /* include the max value */
        return (rand() % (max - min)) + min;
    }

    return -1;
}   
sig_原子信号=0;
sig_原子信号=0;
sig_原子信号t sigusr2_信号=0;
信号原子计数=0;
sig_原子总计数=0;
sigset_t globalset;
int WAIT=1;/*false=0,true=1*/
静态int信号_发送=0;
静态int信号_接收=0;
void*sig1handler1(void*argv);
void*报告处理程序(void*argv);
int随机数(int最小值,int最大值);
内部主(空){
pthread_t threads[2];/*创建一个数组来存储多个线程*/
//int*p_status=&status;
sigfillset(&globalset);
pthread_sigmask(SIG_块和globalset,NULL);
/*生成信号处理线程*/
if(pthread_create(&threads[0],NULL,&sig1handler1,NULL)>0)
{
printf(“线程创建失败!\n”);
返回-1;
}
/*创建报告线程*/
if(pthread_create(&threads[1],NULL,&reporterhandler,NULL)>0)
{
printf(“线程创建失败!\n”);
返回-1;
}
/*通知所有线程同时开始工作*/
等待=0;
int c=0;
而(c<100)
{
int值=随机数(1,2);
如果(值==1)
kill(0,SIGUSR1);
其他的
kill(0,SIGUSR2);
信号发送++;
C++;
美国LEEP(10000);
}
kill(0,SIGINT);
/*等待每个线程完成并连接*/
int i=0;
对于(i=0;i<2;i++)
{
if(pthread_join(threads[i],NULL)>0)
{
printf(“线程[%u]连接失败!\n”,(未签名int)线程[i]);
返回-1;
}
printf(“线程[%u]返回。\n”,(无符号int)线程[i]);
}
printf(“父进程[%d]成功退出。\n”,getpid());
返回退出成功;
}
void*sig1handler1(void*argv)
{
pthread_t tid=pthread_self();
printf(“线程[%u]sig1handler1:等待信号执行某些工作…\n”,(unsigned int)tid);
//sigset_t myset;
//sigfillset(&myset);
//sigdelset(&myset,SIGINT);
//sigdelset(&myset,SIGUSR1);
//pthread_sigmask(SIG_SETMASK,&myset,NULL);
/*等待信号开始工作*/
while(等待);
int-sig;
整数计数=0;
而(1)
{
sigwait(&globalset,&sig);
if(sig==SIGUSR1)
{
sigusr1_信号++;
信号++;
计数++;
//printf(“thread1:捕捉到的信号!\n”);
}
else if(sig==SIGINT)
{
printf(“线程1:捕捉到SIGINT信号,检测到SIGUSR1%d次,并终止!\n”,计数);pthread_退出(NULL);
}
}
//printf(“线程[%u]sig1handler1:正在做一些工作!\n”,(unsigned int)tid);
//返回(无效*)退出成功;
//返回(void*)空;
pthread_exit(NULL);
}
void*报告处理程序(void*argv)
{
pthread_t tid=pthread_self();
printf(“线程[%u]报告器:正在等待信号做一些工作…\n”,(unsigned int)tid);
int-sig;
整数计数=0;
//sigset_t myset;
//sigfillset(&myset);
//sigdelset(&myset,SIGINT);
//sigdelset(&myset,SIGUSR1);
//sigdelset(&myset,SIGUSR2);
//pthread_sigmask(SIG_SETMASK,&myset,NULL);
/*等待信号开始工作*/
while(等待);
而(1)
{
sigwait(&globalset,&sig);
if(sig==SIGUSR1)
{
sigusr1_信号++;
信号++;
计数++;
totalcount++;
信号_接收++;
}
else if(sig==SIGUSR2)
{
sigusr2_信号++;
信号++;
计数++;
totalcount++;
信号_接收++;
}
else if(sig==SIGINT)
{
printf(“报告者:SIGUSR1检测到%d次\n”,SIGUSR1\u信号);
printf(“报告者:SIGUSR2检测到%d次\n”,SIGUSR2\u信号);
printf(“报告器:检测到%d个信号\n”,totalcount);
printf(“报告者:信号发送%d\n”,信号发送);
printf(“报告者:接收到的信号%d\n”);
pthread_exit(NULL);
}
/*检测到10个信号后显示报告*/
如果(计数=10)
sigusr1_信号、sigusr2_信号);
计数=0;
}
}
//printf(“线程[%u]报告器:正在做一些工作!\n”,(unsigned int)tid);
pthread_exit(NULL);
}
整数随机数(整数最小值,整数最大值)
{
如果(最小值<最大值)
{
max=max+1;/*包括最大值*/
返回值(rand()%(max-min))+min;
}
返回-1;
}   
  • 信号[可以]发送到所有pthread[并且]可以由多个pthread同时处理吗
不是同时。这些是可能的:

  • 向进程()发送信号:在这种情况下,任何侦听信号的线程都可以接收信号,但只有一个线程可以接收信号
  • 向进程组发送信号:该信号将发送到该组中的所有进程
  • 将信号发送到特定线程():现在您正在将其发送到特定的线程ID
  • 原型:

    int pthread_kill(pthread_t thread, int sig);
    
    在您的例子中,我认为向所有线程传递信号的唯一方法是沿着所有线程进行迭代