【Linux】一种多线程创建、监视手段

目前对Linux的多进程、多线程理解还不够深入。在现有理解的基础上,写了一套多线程的创建、维护例程。具备以下特性:
1.批量创建,类似于注册;
2.批量监视;
3.重启机制

直接上代码,注释很详细

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

//定义最大线程数
#define MAX_THREAD  3

//线程标号
typedef enum{
    THREAD0 = 0,
    THREAD1,
    THREAD2
}ThreadNameT;

//线程入口函数指针
typedef void*(*cmf)(void *arg);

//线程控制块
//将每个线程抽象成由线程号、线程入口函数、监视错误码组成的结构体
typedef struct{
    pthread_t   tid;        //线程号
    cmf         pfun;       //入口函数
    int         watch_err;  //监视错误码
}threadsCBT;

//线程锁
pthread_mutex_t thrlock;
threadsCBT      thrSCB[MAX_THREAD];//有几个线程就创建几个线程控制块

//线程0
void *thread_0(void *arg)
{
    //人为让其打印5次后退出,验证监视功能
    for(int i = 0;i < 5; i++)
    {
        pthread_mutex_lock(&thrlock);
        printf("thread:this is thread 0 i->%d\n",i);
        pthread_mutex_unlock(&thrlock);
        usleep(1000000);
    }
}

//线程1
void *thread_1(void *arg)
{
    //人为让其打印5次后退出,验证监视功能
    for(int i = 0;i < 5; i++)
    {
        pthread_mutex_lock(&thrlock);
        printf("thread:this is thread 1 i->%d\n",i);
        pthread_mutex_unlock(&thrlock);
        usleep(1000000);
    }
}

//线程2
void *thread_2(void *arg)
{
	//人为让其打印5次后退出,验证监视功能
    for(int i = 0;i < 5; i++)
    {
        pthread_mutex_lock(&thrlock);
        printf("thread:this is thread 2 i->%d\n",i);
        pthread_mutex_unlock(&thrlock);
        usleep(1000000);
    }
}

//线程块初始化,主要是对各个pfun进行注册
void thrSCBInit()
{
    memset(&thrSCB,0,sizeof(thrSCB));
    thrSCB[THREAD0].pfun = thread_0;
    thrSCB[THREAD1].pfun = thread_1;
    thrSCB[THREAD2].pfun = thread_2;
}

int main()
{
    int i;
    int pthread_kill_err;

    thrSCBInit();
    pthread_mutex_init(&thrlock,NULL);

    //批量创建线程,此处不用pthread_join是因为不希望创建子线程后阻塞主线程
    for(i = 0;i < MAX_THREAD; i++)
    {
        pthread_create(&thrSCB[i].tid,NULL,thrSCB[i].pfun,NULL);
        pthread_detach(thrSCB[i].tid);
    }

    //线程监视函数
    while(1)
    {
        pthread_mutex_lock(&thrlock);
        printf("\n");

        //注:必须先获得所有线程的pthread_kill返回码,用于后续判断线程是否存活
        //如果单独获得返回码,然后单独进行线程重启,会有几率造成重启的线程tid与其他已结束的线程重复
        //导致本来结束的线程,调用pthread_kill返回存活,导致无法重启
        for(i = 0;i < MAX_THREAD; i++)
        {
            thrSCB[i].watch_err = pthread_kill(thrSCB[i].tid,0);
        }

        for(i = 0;i < MAX_THREAD; i++)
        {
            //如果线程不存在,则重启
            if(thrSCB[i].watch_err == ESRCH)
            {
                printf("watch :thread %d is quit,restart it\n",i);
                pthread_create(&thrSCB[i].tid,NULL,thrSCB[i].pfun,NULL);
                pthread_detach(thrSCB[i].tid);
            }
            //如果发送信号非法
            else if(pthread_kill_err == EINVAL)
            {
                printf("watch :thread %d send signal vailed\n",i);
            }
            //否则为线程在运行
            else
            {
                printf("watch :thread %d is alive\n",i);
            }    
        }
        printf("\n");
        pthread_mutex_unlock(&thrlock);
        //每隔3秒监视一次
        usleep(3000000);
    }

    return 0;
}

编译运行后如下所示,可以发现线程正常打印时监视功能判断为存活。当线程打印完5次后退出,之后被监视功能发现,又成功将其重启。

wy@wy-virtual-machine:~/test$ ./t
thread:this is thread 0 i->0
thread:this is thread 2 i->0
thread:this is thread 1 i->0

watch :thread 0 is alive
watch :thread 1 is alive
watch :thread 2 is alive

thread:this is thread 1 i->1
thread:this is thread 0 i->1
thread:this is thread 2 i->1
thread:this is thread 1 i->2
thread:this is thread 0 i->2
thread:this is thread 2 i->2

watch :thread 0 is alive
watch :thread 1 is alive
watch :thread 2 is alive

thread:this is thread 1 i->3
thread:this is thread 2 i->3
thread:this is thread 0 i->3
thread:this is thread 1 i->4
thread:this is thread 2 i->4
thread:this is thread 0 i->4

watch :thread 0 is quit,restart it
watch :thread 1 is quit,restart it
watch :thread 2 is quit,restart it

thread:this is thread 0 i->0
thread:this is thread 2 i->0
thread:this is thread 1 i->0
thread:this is thread 2 i->1
thread:this is thread 0 i->1
thread:this is thread 1 i->1
thread:this is thread 0 i->2
thread:this is thread 1 i->2
thread:this is thread 2 i->2

watch :thread 0 is alive
watch :thread 1 is alive
watch :thread 2 is alive

thread:this is thread 2 i->3
thread:this is thread 1 i->3
thread:this is thread 0 i->3
thread:this is thread 1 i->4
thread:this is thread 2 i->4
thread:this is thread 0 i->4

watch :thread 0 is quit,restart it
watch :thread 1 is quit,restart it
watch :thread 2 is quit,restart it

thread:this is thread 0 i->0
thread:this is thread 2 i->0
thread:this is thread 1 i->0
thread:this is thread 2 i->1
thread:this is thread 0 i->1
thread:this is thread 1 i->1
thread:this is thread 0 i->2
thread:this is thread 2 i->2
thread:this is thread 1 i->2

猜你喜欢

转载自blog.csdn.net/spiremoon/article/details/105979641