linux 多线程消息广播

来源:互联网 发布:波士顿矩阵图怎么制作 编辑:程序博客网 时间:2024/06/01 09:04

    最近在工作中遇到了问题一个纠结问题:一个底层通用的模块,在应用层有许多线程使用。该模块大多数情况下都是正常的,模块出问题之后或基于其他考虑需要重启底层模块,底层重启了之后理论上是应用层需要释放当前资源,重新开始应用层业务。

    为了实现该目标,当前以使用方式是:底层模块重启前调用每一个应用程接口,通知他们释放当前资源。但感觉这个设计有些缺陷:完全破坏了底层模块的封装完整性。

    然后首先想到的是应用层,自己不停的检测底层模块的状态,但是觉得有点不太麻烦,需要一个while(1){check},有点低效

    最后想到了tcp 中的组播思想,首先将需要监控底层模块的线程加入一个分组内,当底层模块状态需要发生改变时,给组内每个线程发送一个通知消息。应用线程接收到通知消息之后,释放当前资源,重新开始业务。

    下面是这个线程组播的消息的源代码,源码仅仅是一个demo,用于阐述线程组播思想的框架,在实际引用中需要用户自己完善。

#include <signal.h>

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 5
typedef struct{
    pthread_t pid_th;
    void (*sig_pro)(int);
}board_sig;

board_sig siglist[MAX];

void th1_sighandler(int signo)
{
    pthread_t   tid = pthread_self();
     
    printf("thread with pid:%lu receive signo:%d, I am th1 pro\n", tid, signo);
    return;
}


void th2_sighandler(int signo)
{
    pthread_t   tid = pthread_self();
     
    printf("thread with pid:%lu receive signo:%d, I am th2 pro\n", tid, signo);
    return;
}


void th3_sighandler(int signo)
{
    pthread_t   tid = pthread_self();
     
    printf("thread with pid:%lu receive signo:%d, I am th3 pro\n", tid, signo);
    return;
}


void sighandler(int signo)
{
    pthread_t   tid = pthread_self();
    int i = 0;
    
    for(i = 0; i < MAX; i++)
    {
        if(tid == siglist[i].pid_th)
        {
            siglist[i].sig_pro(signo);
        }
    }
}


void Init_User1Sig_Board(pthread_t pid_th, void (*sig_pro)(int))
{
    int i = 0;
    
    for(i = 0; i < MAX; i++)
    {
        if(siglist[i].pid_th == 0)
        {
            siglist[i].pid_th = pid_th;
            siglist[i].sig_pro = sig_pro;
            break;
        }
    }
}
 
User1Sig_Board_Pro()
{
    int i = 0;
    
    for(i = 0; i < MAX; i++)
    {
        if(siglist[i].pid_th != 0)
        {
            printf("i = %d, pid_th = %lu\n", i, siglist[i].pid_th);
            pthread_kill(siglist[i].pid_th,SIGUSR1);
            //usleep(1000);
        }
    }
}

void * thr1_fn(void *arg)
{
    pthread_t   tid = pthread_self();
    printf("thread 1 with tid:%lu\n", tid);
    
    Init_User1Sig_Board(tid, th1_sighandler);
    sleep(15);
    
    return NULL;
}
 
void *thr2_fn(void *arg)
{
    pthread_t       tid = pthread_self();

    printf("thread 2 with tid:%lu\n", tid);
    Init_User1Sig_Board(tid, th2_sighandler);
    sleep(15);
    
    return NULL;
}
 
void *thr3_fn(void *arg)
{
    pthread_t   tid = pthread_self();

    printf("thread 3 with tid:%lu\n", tid);
 
    Init_User1Sig_Board(tid, th3_sighandler);
    sleep(15);
 
    return NULL;
}



 
int main(void)
{
    int     rc, err;
    pthread_t   thr1, thr2, thr3, thrm = pthread_self();
    
    struct sigaction    action;
    action.sa_flags = 0;
    action.sa_handler = sighandler;
       
    sigaction(SIGUSR1, &action, NULL);
    printf("thread main with pid %lu\n",thrm);
    err = pthread_create(&thr1, NULL, thr1_fn, NULL);
    if (err != 0) {
        printf("error in creating pthread:%d\t%s\n",err, strerror(rc));
        exit(1);
    }
 
     
    /*  pthread_kill(thr1, SIGALRM);    send a SIGARLM signal to thr1 before thr2 set the signal handler, then the whole process will be terminated*/
    err = pthread_create(&thr2, NULL, thr2_fn, NULL);
    if (err != 0) {
        printf("error in creating pthread:%d\t%s\n",err, strerror(rc));
        exit(1);
    }
     
    err = pthread_create(&thr3, NULL, thr3_fn, NULL);
    if (err != 0) {
        printf("error in creating pthread:%d\t%s\n",err, strerror(rc));
        exit(1);
    }
 
    sleep(10);
    //内部产生的信号,只有指定的线程能收到,因此要向所有线程发送
    User1Sig_Board_Pro();
    
    pthread_join(thr1, NULL);   /*wait for the threads to complete.*/
    pthread_join(thr2, NULL);
    pthread_join(thr3, NULL);
    printf("main ends\n");
    return 0;
}


编译调试结果:

# gcc c.c -o c -lpthread
# ./c
thread main with pid 3075667648
thread 3 with tid:3058879296
thread 2 with tid:3067272000
thread 1 with tid:3075664704
i = 0, pid_th = 3058879296
i = 1, pid_th = 3067272000
i = 2, pid_th = 3075664704
thread with pid:3058879296 receive signo:10, I am th3 pro
thread with pid:3067272000 receive signo:10, I am th2 pro
thread with pid:3075664704 receive signo:10, I am th1 pro
main ends