写在最前面
华清远见教育集团
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到子线程的结束状态,然后进行线程回收。