微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 基于多线程的环境监控系统下位机的设计

基于多线程的环境监控系统下位机的设计

时间:10-17 来源:互联网 点击:

arg); / /决策线程函数

int dat a[ 12] ; / /数据缓冲区,用于存放线程间共享的数据函数

main()

{

/ /初始化工作

……

pthread_t wat chd og; / /线程号

pthread_t collect ion;

pthread_t commun ication;

pthread_t deci se;

pthread_at t r_init(); / /初始化线程属性

pthread_at t r_setdetach st at e(); / /不对线程进行重新归并

pthread_at t r_set s ched param(); / /设置线程的优先级

sem_init(); / /对相关信号量进行初始化

pth read_creat e(); / /创建新线程

/ /启动GUI程序

……

}

  4. 2线程的同步机制

同步机制是否合理是多线程应用程序运行是否稳定的关键。在程序设计时,需考虑到可能引起数据毁坏的多线程数据访问冲突以及如何使用同步技术避免这种冲突。Linux操作系统实现同步机制的方法有信号量(semaphore)和互斥量(mutex),这两种方法相似,但各有侧重。信号量侧重于一个线程被另一个线程激活,常有先后执行的关系。而互斥量则保护某一共享内存任一时刻只有一个线程访问。网络通信线程和数据采集与存储线程之间的同步通过信号量来实现。

为了防止系统资源泄漏,保持各个线程的同步,主线程需要初始化数据采集驱动代码,为数据采集做好准备;申请相应的内存空间,用于存放采集到的实时数据;定义好各个信号量和互斥量。

  4. 3线程的实现方法

数据采集与存储线程是获取数据的起始线程,由GU I线程创建,网络通信线程和决策线程是由数据采集与存储线程激活。下位机开始运行后,数据采集与存储线程启动,每隔5 s运行1次,读DI、AI接口的状态,并把这些状态和此刻的时间存入SQ Lite数据库中。数据采集与存储线程每运行一次,对信号量sem_decise和sem_ com进行一次post操作,分别激活决策线程和网络通信线程。数据采集与存储线程的同步流程如图4所示。

#FormatImgID_3#

图4数据采集与存储线程的同步流程

数据采集与存储线程作为系统的数据源头,它激活了其它2个子线程,与之相对应,被激活的子线程随着它的结束而结束。线程在未接受到信号量激活时处于阻塞状态,不占用系统资源。前台处理用户界面的GUI线程与后台的工作线程之间是独立的。GU I线程提供友好的人机界面,它把被监控对象的信息实时显示在图形界面上,供现场工作人员查询和设置。

监控程序的每个线程都需要对存放被监控对象实时状态的数据缓冲区进行访问。由于Linux操作系统允许多个线程同时对某一数据缓冲区进行读操作,但在同一时刻对该数据缓冲区只能有一个写操作。GUI线程需要定时刷屏,更新被监控对象的实时状态,因而需要定时对缓冲区进行读操作,而数据采集与存储线程定时地对该缓冲区进行写操作,它们之间没有触发关系,是相互独立运行的。因此,需要对缓冲区设置一个互斥量,确保任一时刻这两个线程只有一个能对其进行访问。

数据采集与存储线程对缓冲区进行写操作之前,先对互斥量进行加锁操作,把实时状态写入数据缓冲区后,再进行解锁。这样避免了因与GU I线程争夺资源而造成系统不稳定的现象。上锁与解锁操作代码如下:

void * thr ead_collect ion(void * arg)

{

……

pthread_mu tex_lock(dat a_mu tex); / /上锁操作

read(fd, dat a, s izeof(dat a)); / /写实时状态到data缓冲区

pthread_mu tex_unl ock(dat a_m ut ex); / /解锁操作

/ /激活网络通信线程、决策线程,并写数据到数据库

……

}

同样,GUI线程中也需要对缓冲区进行相应的上锁、解锁操作。

网络通信线程和决策线程由GUI线程创建,由数据采集与存储线程激活,都是每5 s运行1次。

由于GPRS模块通过串口与下位机相连,并采用透明传输模式,即有数据即传输,因此,网络通信线程只需要定时对串口写操作就可以完成数据传输任务。网络通信线程先打开串口,设置串口的波特率、数据位、校验位等属性,然后等待数据采集与存储线程的信号量将其激活,第一次被激活后,进入了一个w hile循环,执行一次串口写操作,再等待下一次被激活。网络通信线程被激活的条件是数据采集与存储线程对信号进行了一次加1操作,即sem_ post(sem_2)。网络通信线程的关键代码如下:

fd= open(“/ dev/ t t ySC4”, O_RDWR);

set_sp eed(fd, 9 600); / /设置波特率

set_parit y(fd, 8, 1, %n); / /设置数据位、奇偶校验位

sem_w ait(s em_2); / /等待信号量激活

w h ile(1){

w rit e(fd, buf , sizeof(buf)); / /对串口写操作,发送数据

sem_w ait(sem_2); / /等待下一次信号量激活

}

pth read_exit(“thread exit \ n”); / /线程退出

决策线程的任务是对当前被监控对象的状态进行判断,如果

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top