目前对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