1. 程式人生 > >基於Linux C多執行緒軟體框架實現

基於Linux C多執行緒軟體框架實現

之前寫過一篇基於C語言連結串列實現的工作任務註冊與執行,連結如下:

https://blog.csdn.net/morixinguan/article/details/77986553

後面使用它演變成為了另外一個框架,也就是多執行緒,當時的設計思路主要是為了服務測試程式。

搞過RK(瑞芯微)平臺的都知道,這個平臺提供了一個PCBA的測試程式,它是基於Linux核心連結串列框架實現的,但該程式有一點不好的地方就在於框架用起來不是那麼的簡單,因此我針對該專案做了自己的優化,使之用起來簡單,可定製性也高,程式在百度應該可以搜尋得到。

RK PCBA實現效果:https://wenku.baidu.com/view/09257cb777a20029bd64783e0912a21615797f58.html

我實現的專案具體的資料型別以及資料結構:

typedef unsigned char  u8 ;
typedef unsigned int   u32;
typedef unsigned short u16;
typedef char  s8 ;
typedef int   s32;
typedef short s16;
typedef char  * pchar;
typedef int   * pint ;
typedef short * pshort ;
typedef void    No_return;
typedef void (*work_fun)();

#define SUCCESS 0
#define ZERO    0
#define ERROR  -1
#define Not_sorted -1
#define Positive 1
#define Reverse 0

typedef struct __Work
{
	//任務編號
	//根據任務編號決定工作任務的優先順序
	//編號越小,優先順序越高
	s32 work_num ;
	//任務名稱 
	pchar work_name ;
	//根據相應的任務名稱,處理相應的任務
	void (*work_handler)(int); 
	struct __Work *next ;
}work;
typedef work * _work ;

使用的API,通過巨集定義來呼叫,也可以呼叫子函式,巨集定義使用起來非常簡單方便,但可拓展性不高,程式設計師可以根據自己的需求去自己定義巨集函式,而實際子函式使用起來則會更加靈活,可自己定製。

#define __INIT_WORK(_work)			\
	do {							\
		_work = Init_cwork(_work);		\
	} while (0)

#define INIT_WORK(work_node) \
	 _work work_node = NULL ; \
	__INIT_WORK(work_node); 

#define REGISTER_WORK(__work,new_work) \
	Register_work_fuc(__work,new_work);
		
#define SCHEDULING_WORK(work_node,direction,array_size) \
	Run_Priority_work(work_node,direction,array_size);

	
#define DESTROY_WORK(work_node,array) \
		work_node = Destroy_work(work_node ,array);

//初始化一個子任務 
_work Init_cwork();
//建立一個子任務
_work create_cwork(s32 work_num,pchar work_name ,work_fun work_fuc) ;
//註冊子任務
No_return Register_work_fuc(_work __work,_work new_work);
//查詢子任務的編號
s32 Find_Work_Num(_work headler,s32 work_num);
//查詢子任務的名稱
pchar Find_Work_Name(_work headler,pchar work_name) ;
//執行子任務----根據任務名稱來執行
s32 Run_work_for_work_name(_work headler,pchar work_name) ;
//銷燬一個子任務
s32 Destroy_cwork(_work headler,pchar work_name);
//銷燬全部任務 
_work Destroy_work(_work headler,_work array);
//工作優先順序排程執行--->工作編號小的優先順序高,依次類推
s32 Run_Priority_work(_work handler,s32 direction,const s32 work_array_size) ;

具體實現如下: work.h

#ifndef __WORK_H
#define __WORK_H
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h> 
#include <assert.h>
#include <pthread.h>
#define NR(x) (sizeof(x)/sizeof(x[0]))
typedef unsigned char  u8 ;
typedef unsigned int   u32;
typedef unsigned short u16;
typedef char  s8 ;
typedef int   s32;
typedef short s16;
typedef char  * pchar;
typedef int   * pint ;
typedef short * pshort ;
typedef void    No_return;
typedef void (*work_fun)();

#define SUCCESS 0
#define ZERO    0
#define ERROR  -1
#define Not_sorted -1
#define Positive 1
#define Reverse 0

typedef struct __Work
{
	//任務編號
	//根據任務編號決定工作任務的優先順序
	//編號越小,優先順序越高
	s32 work_num ;
	//任務名稱 
	pchar work_name ;
	//根據相應的任務名稱,處理相應的任務
	void (*work_handler)(int); 
	struct __Work *next ;
}work;
typedef work * _work ;

#define __INIT_WORK(_work)			\
	do {							\
		_work = Init_cwork(_work);		\
	} while (0)

#define INIT_WORK(work_node) \
	 _work work_node = NULL ; \
	__INIT_WORK(work_node); 

#define REGISTER_WORK(__work,new_work) \
	Register_work_fuc(__work,new_work);
		
#define SCHEDULING_WORK(work_node,direction,array_size) \
	Run_Priority_work(work_node,direction,array_size);

	
#define DESTROY_WORK(work_node,array) \
		work_node = Destroy_work(work_node ,array);

//初始化一個子任務 
_work Init_cwork();
//建立一個子任務
_work create_cwork(s32 work_num,pchar work_name ,work_fun work_fuc) ;
//註冊子任務
No_return Register_work_fuc(_work __work,_work new_work);
//查詢子任務的編號
s32 Find_Work_Num(_work headler,s32 work_num);
//查詢子任務的名稱
pchar Find_Work_Name(_work headler,pchar work_name) ;
//執行子任務----根據任務名稱來執行
s32 Run_work_for_work_name(_work headler,pchar work_name) ;
//銷燬一個子任務
s32 Destroy_cwork(_work headler,pchar work_name);
//銷燬全部任務 
_work Destroy_work(_work headler,_work array);
//工作優先順序排程執行--->工作編號小的優先順序高,依次類推
s32 Run_Priority_work(_work handler,s32 direction,const s32 work_array_size) ;

#endif //__WORK_H

work.c

#include "work.h"


_work Init_cwork()
{
	_work handler =  NULL ;
	handler = malloc(sizeof(work)) ;
	assert(handler != NULL);
	memset(handler,ZERO,sizeof(work));
	handler->work_num = 0 ;
	handler->work_name = NULL ; 
	handler->work_handler = NULL ;
	handler->next = NULL ;
	return handler ;
}

_work create_cwork(s32 work_num , pchar work_name, work_fun work_fuc)
{
	_work handler =  NULL ;
	handler = malloc(sizeof(work)) ;
	assert(handler != NULL);
	memset(handler,ZERO,sizeof(work));
	handler->work_num = work_num ;
	handler->work_name = work_name ; 
	handler->work_handler = work_fuc ;
	handler->next = NULL ;
	return handler ;
}

No_return Register_work_fuc(_work __work,_work new_work)
{
	assert(__work != NULL);
	_work work_handler = __work ;
	while(NULL != work_handler->next)
		work_handler = work_handler->next ; 
	work_handler->next = new_work ; 
}

s32 Find_Work_Num(_work headler,s32 work_num)
{
	assert(headler != NULL);
	_work temp = headler->next ;
	while(NULL != temp->next)
	{
		if(temp->work_num == work_num)
			return temp->work_num ;
		temp = temp->next;
	}
	return temp->work_num ;
} 

pchar Find_Work_Name(_work headler,pchar work_name)
{
	assert(headler != NULL);
	_work temp = headler->next ;
	while(NULL != temp->next)
	{
		if(temp->work_name == work_name)
			return temp->work_name ;
		temp = temp->next;
	}
	return temp->work_name ;
} 


s32 Run_work_for_work_name(_work headler,pchar work_name)
{
	assert(headler != NULL);
	pthread_t   tid ; 
	s32 ret ;
	_work temp = headler ;
	while(NULL != temp->next)
	{
		temp = temp->next;
		if(temp->work_name == work_name){
			//建立執行緒
			ret = pthread_create(&tid , NULL , 	(void *)temp->work_handler , temp->work_name);
			if(ret != SUCCESS){
				perror("create pthread fail");
				return ERROR ; 
			}
			//執行緒分離
			ret = pthread_detach(tid);
			return SUCCESS;
		}
	}
	if(temp->work_name == work_name){
		ret = pthread_create(&tid , NULL , 	(void *)temp->work_handler , temp->work_name);
		if(ret != SUCCESS){
			perror("create pthread fail");
			return ERROR ; 
		}
		ret = pthread_detach(tid);
		return SUCCESS ;
	}
	printf("not this work , return ERROR!\n");
	return ERROR;
}

static s32 Run_work_for_work_num(_work headler,s32 work_num)
{
	assert(headler != NULL);
	pthread_t   tid ; 
	s32 ret ;
	_work temp = headler ;
	while(NULL != temp->next)
	{
		temp = temp->next;
		if(temp->work_num == work_num){
			//建立執行緒
			ret = pthread_create(&tid , NULL , 	(void *)temp->work_handler , temp->work_num);
			if(ret != SUCCESS){
				perror("create pthread fail");
				return ERROR ; 
			}
			//執行緒分離
			ret = pthread_detach(tid);
			return SUCCESS;
		}
	}
	if(temp->work_num == work_num){
		ret = pthread_create(&tid , NULL , 	(void *)temp->work_handler , temp->work_num);
		if(ret != SUCCESS){
			perror("create pthread fail");
			return ERROR ; 
		}
		ret = pthread_detach(tid);
		return SUCCESS ;
	}
	printf("not this work , return ERROR!\n");
	return ERROR;
}

static No_return Sort_work_num(s32 *buf, s32 len ,int direction)
{
	s32 min;
	s32 index;
	s32 i, j , n;
	if(direction == Positive)
	{
		for(i = ZERO; i < len - 1; i++)
		{
			min = buf[i];
			index = i;
			for(j = i; j < len; j++)
			{
				if(buf[j] < min)
				{
					min = buf[j];
					index = j;
				}
			}
			buf[index] = buf[i];
			buf[i] = min;
		}
	}
	else if(direction == Reverse)
	{
		for(i = 0 ; i < len ; i++)
		{
			for(j = 0 ; j < len ; j++)
			{
				if(buf[i] < buf[i+1])
				{
					n = buf[i] ;
					buf[i] = buf[i+1] ;
					buf[i+1] = n ;
				}
			}
		}
	}
	else 
	{
		return ;
	}

}

s32 Run_Priority_work(_work handler,s32 direction,const s32 work_array_size)
{
	
	s32 count = 0 ;
	s32 i ;
	assert(handler != NULL);
	_work temp = handler->next ;
	s32 Curent_node_Array[work_array_size];
	
	while(temp != NULL){
		Curent_node_Array[count] = temp->work_num ;
		temp = temp->next ;
		if(count < work_array_size)
			count++ ;
	}
	Sort_work_num(Curent_node_Array,NR(Curent_node_Array),direction) ;
	for(i = 0 ; i < NR(Curent_node_Array) ; i++)
		Run_work_for_work_num(handler,Curent_node_Array[i]);
	return SUCCESS ;
}



s32 Destroy_cwork(_work headler,pchar work_name)
{
	assert(headler != NULL);
	_work temp = headler ;
	_work temp_header_prev = NULL ;
	while(NULL != temp->next)
	{
		temp_header_prev = temp ;
		temp = temp->next ; 
		if(temp->work_name == work_name)
		{
			if(temp->next != NULL)
			{
				temp_header_prev->next = temp->next ;
				free(temp);
				temp = NULL ;
			}
			else
			{
				temp_header_prev->next = NULL ; 
				free(temp);
				temp = NULL ;
			}
			return SUCCESS ;
		}
	}
	printf("Not Work node\n");
	return ERROR ;
}

_work Destroy_work(_work headler,_work array)
{
	s32 i ; 
	assert(headler != NULL);
	_work temp = headler ;
	for(i = ZERO ; i < NR(array) ; i++)
		Destroy_cwork(headler,array[i].work_name);
	headler = NULL ;
	return headler ;
}

如何使用?

1、初始化工作

2、工作任務註冊

3、排程任務執行

#include<stdio.h>
#include "work.h"



int Test1(int work_num) ;
int Test2(int work_num) ;
int Test3(int work_num) ;
int Test4(int work_num);
int Test5(int work_num);


//結構體描述:
/*
	ep:
	{1,"Test1",Test1},
	1表示任務編號,同時也表示在LCD的哪一行進行顯示
	"LCD_Test"表示任務名稱
	LCD_Test表示任務執行函式
*/
work work_Register[] = 
{
	{1,"Test1",Test1},
	{2,"Test1",Test2},
	{3,"Test3",Test3},
	{4,"Test4",Test4},
	{5,"Test5",Test5},
};

int main(void)
{
	s32 i ;
	//1、定義頭指標,初始化頭節點
	INIT_WORK(work_node);
	for(i = ZERO ; i < NR(work_Register) ; i++) 
	{
		//2、實現工作任務的註冊
		REGISTER_WORK(work_node , create_cwork(work_Register[i].work_num ,work_Register[i].work_name , work_Register[i].work_handler));
	}
	//3、排程工作任務,編號從小到大排序
	SCHEDULING_WORK(work_node,Positive,NR(work_Register));
	while(True)
	{
		;
	}
	//DESTROY_WORK(work_node,work_Register);
	return SUCCESS ;
}

int Test1(int work_num) 
{
	
}

int Test2(int work_num) 
{
	
}

int Test3(int work_num) 
{
	
}

int Test4(int work_num) 
{
	
}

int Test5(int work_num) 
{
	
}

當然程式可以進一步的優化和定製,在目前看來,該框架可以完全滿足我目前的要求,非常穩定且易於維護和拓展。