写在最前面

华清远见教育集团
15年专注高端IT培训
做良心教育,做专业教育,做受人尊敬的职业教育

创客学院官网:http://www.makeru.com.cn/
华清远见创客学院嵌入式课程链接:http://www.makeru.com.cn/emb
华清远见创客学院物联网课程链接:http://www.makeru.com.cn/iot

 

正文

 

线程指的是共享相同地址空间的多个任务,每个任务是一个线程,而这种多线程的机制构成一个进程。既然多个线程能够共享进程中的资源,为了避免不同线程对资源读写造成的冲突,那我们就要引入同步互斥机制。

 

 

 

软件框架


在main程序中申请的很多线程,每个线程代表一个任务处理,进而实现多任务并发的机制。这里A9应用层程序设计为一个应用服务器,不仅要接收底层送过来的数据包,解析处理后的数据最终要送到html文件中,最后经浏览器解析展示给用户看;而且还要求能接收客户端用户发出的命令,然后进一步实现某个设定。把整个项目功能分成多个任务,有处理客户端请求线程、解析底层数据包并填充到结构体线程、处理数据并传递到网页端线程,等等。。。这么多线程,要考虑到线程之间的同步互斥机制,如何对资源进行访问。

 

目的:本文将把这种多线程处理的思想,构建成一个用户程序框架,最终实现多个线程的切换。暂时不实现上图所示的这些功能。重点是项目架构的实现。

 

项目目录结构

root@linux:step1# tree -L 1

.
├── data_global.c   定义全局信息(IPC对象id和key值、条件锁、互斥锁)
├── data_global.h   一些全局变量、全局信息的声明(全局宏定义、全局函数声明、全局变量声明)
├── main.c              主线程,用于多个子线程和锁的统一申请、注销线程资源、注销消息队列 共享内存 信号量等等
├── Makefile        负责整个项目的编译
├── obj             这是一个目录,所有编译生成的中间文件在这个目录中
├── our_storage     最终编译输出的可执行文件
├── pthread_analysis.c         线程 M0线程数据分析
├── pthread_buzzer.c            线程 A9蜂鸣器控制
├── pthread_camera.c            线程 摄像头模块控制
├── pthread_client_request.c   线程 处理消息队列中的请求
├── pthread_led.c              线程 A9 LED模块
├── pthread_refresh.c          线程 更新共享内存里的实时数据
├── pthread_sms.c              线程 短信模块控制
├── pthread_sqlite.c           线程 数据库
├── pthread_transfer.c         线程 接收M0数据线程
└── sem.h                      主要用于实现函数接口 对信号量的PV操作
1 directory, 15 files

 

主线程与各个子线程的搭建

主线程

#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include "data_global.h"


void release_pthread_resource(int signo);	//释放线程资源


extern pthread_mutex_t 	mutex_client_request,
		        		mutex_refresh,
		        		mutex_sqlite,
			        	mutex_transfer,
			        	mutex_analysis,
			        	mutex_sms,
			        	mutex_buzzer,
			         	mutex_led,
			         	mutex_camera;

extern pthread_cond_t 	cond_client_request,
		        		cond_refresh,
		        		cond_sqlite,
			        	cond_transfer,
			        	cond_analysis,
			        	cond_sms,
			        	cond_buzzer,
			         	cond_led,
			         	cond_camera;


extern struct env_info_clien_addr all_info_RT;	//所有仓库的信息 


extern int msgid;	//消息队列对象 id
extern int shmid;	//共享内存对象 id
extern int semid;	//信号量对象 id


pthread_t id_client_request,
		  id_refresh,
		  id_sqlite,
		  id_transfer,
		  id_analysis,
		  id_sms,
		  id_buzzer,
		  id_led,
		  id_camera;





int main()
{
	//线程互斥锁初始化
	pthread_mutex_init(&mutex_client_request,NULL);
	pthread_mutex_init(&mutex_refresh,NULL);
	pthread_mutex_init(&mutex_sqlite,NULL);
	pthread_mutex_init(&mutex_transfer,NULL);
	pthread_mutex_init(&mutex_analysis,NULL);
	pthread_mutex_init(&mutex_sms,NULL);
	pthread_mutex_init(&mutex_buzzer,NULL);
	pthread_mutex_init(&mutex_led,NULL);
	pthread_mutex_init(&mutex_camera,NULL);

	signal (SIGINT, release_pthread_resource);

	//线程条件锁初始化
	pthread_cond_init(&cond_client_request,NULL);
	pthread_cond_init(&cond_refresh,NULL);
	pthread_cond_init(&cond_sqlite,NULL);
	pthread_cond_init(&cond_transfer,NULL);
	pthread_cond_init(&cond_analysis,NULL);
	pthread_cond_init(&cond_sms,NULL);
	pthread_cond_init(&cond_buzzer,NULL);
	pthread_cond_init(&cond_led,NULL);
	pthread_cond_init(&cond_camera,NULL);

	//线程的创建
	pthread_create(&id_client_request,NULL,pthread_client_request,NULL);  //线程的创建
	pthread_create(&id_refresh, NULL,pthread_refresh,NULL);  			
	pthread_create(&id_sqlite,	NULL,pthread_sqlite,NULL);  			
	pthread_create(&id_transfer,NULL,pthread_transfer,NULL);  	
	pthread_create(&id_analysis,NULL,pthread_analysis,NULL); 
	pthread_create(&id_sms,		NULL,pthread_sms,NULL);  	
	pthread_create(&id_buzzer,	NULL,pthread_buzzer,NULL);	 
	pthread_create(&id_led,		NULL,pthread_led,NULL);  	
	pthread_create(&id_camera,	NULL,pthread_camera,NULL); 	

	//等待线程退出
	pthread_join(id_client_request,NULL);   printf ("pthread1\n");
	pthread_join(id_refresh,NULL);          printf ("pthread2\n");
	pthread_join(id_sqlite,NULL);			printf ("pthread3\n");
	pthread_join(id_transfer,NULL);			printf ("pthread4\n");
	pthread_join(id_analysis,NULL);			printf ("pthread5\n");
	pthread_join(id_sms,NULL);				printf ("pthread6\n");
	pthread_join(id_buzzer,NULL);			printf ("pthread7\n");
	pthread_join(id_led,NULL);				printf ("pthread8\n");
	pthread_join(id_camera,NULL);         	printf ("pthread9\n");

	return 0;
}



void release_pthread_resource(int signo)
{
	//释放与线程相关的资源
	//释放线程锁资源
	pthread_mutex_destroy (&mutex_client_request);   
	pthread_mutex_destroy (&mutex_refresh);   
	pthread_mutex_destroy (&mutex_sqlite);   
	pthread_mutex_destroy (&mutex_transfer);   
	pthread_mutex_destroy (&mutex_analysis);   
	pthread_mutex_destroy (&mutex_sms);   
	pthread_mutex_destroy (&mutex_buzzer);   
	pthread_mutex_destroy (&mutex_led);   
	pthread_mutex_destroy (&mutex_camera); 

 	pthread_cond_destroy (&cond_client_request);
 	pthread_cond_destroy (&cond_refresh);
 	pthread_cond_destroy (&cond_sqlite);
 	pthread_cond_destroy (&cond_transfer);
 	pthread_cond_destroy (&cond_analysis);
 	pthread_cond_destroy (&cond_sms);
 	pthread_cond_destroy (&cond_buzzer);
 	pthread_cond_destroy (&cond_led);
 	pthread_cond_destroy (&cond_camera);

	 //pthread_cancel (id_refresh);  //不采用这种方式
	//使线成分离出来。当这个线程执行完成任务后释放释放资源。不然它会保留退出状态,等待别人来取
	 pthread_detach(id_client_request);
	 pthread_detach(id_refresh);
	 pthread_detach(id_sqlite);
	 pthread_detach(id_transfer);
	 pthread_detach(id_analysis);
	 pthread_detach(id_sms);
	 pthread_detach(id_buzzer);
	 pthread_detach(id_led);
	 pthread_detach(id_camera);

	 printf("all pthread is detached\n");

	 
	 msgctl (msgid, IPC_RMID, NULL);
	 shmctl (shmid, IPC_RMID, NULL);
	 semctl (semid, 1, IPC_RMID, NULL);

	 exit(0);
}

 

各个子线程的函数

//pthread_transfer.c
void *pthread_transfer(void *arg)
{//接收M0数据线程
	printf("pthread_transfer\n");
}



//pthread_refresh.c
void *pthread_refresh(void *arg)
{//更新共享内存里的实时数据
	printf("pthread_refresh\n");
	
}


//pthread_led.c
void *pthread_led(void *arg)
{//A9 LED模块线程
	printf("pthread_led\n");

}



..............
....................

 

最后运行效果

按照程序的思路,主线程先创建各个子线程。内核调度子线程的执行,这里子线程只打印一句话就结束了。子线程执行结束后,主线程get到子线程的结束状态,然后进行线程回收。