您当前的位置:五五电子网电子知识单片机-工控设备嵌入式系统-技术QNX环境下多线程编程 正文
QNX环境下多线程编程

QNX环境下多线程编程

点击数:7480 次   录入时间:03-04 11:49:50   整理:http://www.55dianzi.com   嵌入式系统-技术

    多余的线程只会使程序的复杂性增加,出错的可能性也随之增加。设计程序时要遵循简单、高效、安全的原则,如果用单线程能够很好的完成任务,那么一定不要用多线程。

    2)分析多线程需要共享的数据。

    在多线程程序中常常需要共享一些数据,通常是一些全局变量,如果数据量很大可能需要开辟共享内存区。

    3) 根据共享数据的特点选择需要的保护机制。

    多个线程需要写操作的变量可以用互斥体保护,经常需要读操作而很少进行写操作的可以用读/写锁保护等。

    4) 分析工作线程需要访问资源。

    工作线程可能需要访问硬件,等待硬件响应、可能需要访问某一数据库、也可能不访问任何资源只是进行一些计算等等。这时需要考虑相应的同步机制,可以用条件变量结合互斥体,也可以用更为简单的sleepon锁。

    5)进行线程的清理工作。

    线程完成工作后可能会自动退出,也可能会阻塞在某处,甚至工作线程还没完成工作的时候主线程已经退出,造成整个进程的结束,使程序失败。有多种方法可以完成线程的清理工作,可以让主线程调用pthread_join()函数清理工作线程,可以用屏障同步机制清理,也可以用条件变量来完成清理工作。

    3.2多线程程序的基本结构

    多线程编程的结构有很多种,但基本的编程结构总结起来有三种:流水线结构、工作组结构、客户端/服务器结构。这三种结构可以以任意方式组合,来满足实际工程的需求。

    1) 流水线结构

    在流水线结构中,需要处理的“数据”串行地被一组线程顺序处理,每个线程依次在每个数据元素上执行一个特定的操作,完成操作后将结果传递给流水线中的下一个线程。如图1所示。


    2) 工作组结构

    在工作组结构中,数据有一组线程分别独立地处理,每个线程处理不同的部分。由于所有的工作线程在不同的数据部分上执行相同的操作,这种模式通常被称为SIMD(单指令多数据流)并行处理。但是工作组中的线程可以不使用SIMD模型,他们可以在不同的数据上执行不同的操作。工作组结构是多线程程序应用较多的一种结构。如图2所示

图2 工作组结构


    3) 客户端/服务器结构

    在客户/服务器结构中,客户请求服务器对一组数据执行某个操作。客户端独立地执行操作,而客户端或者等待服务器执行的结果,或者并行执行另外的任务,在后面需要时在查找结果。这种结构又是一种对某些公共资源同步管理的简单方式。如图3


    4 QNX Neutrino内核对于线程功能的扩展

    具有Neutrino内核的QNX6操作系统对线程的功能进行了扩展,提供了一些POSIX标准没有提供的功能。

    1)POSIX标准规定使用互斥体的线程必须在同一进程内,作为扩展QNX支持在不同进程中的线程使用互斥体。如果在两个进程间创建一块共享内存,并在内存中初始化一个互斥体,那么两个进程之间的线程可以用这个互斥体来进行同步操作,这是POSIX做不到的。

    2) QNX操作系统还提出了一种独特的“线程池”概念。当程序需要很多线程同时工作时,利用“线程池”可以将线程的个数限定在一定的范围内。“高水位”、“低水位”的概念分别对应着程序中的最大线程数和最小线程数。当程序中线程数目小于“低水位”时,“线程池”会自动创建新的线程进行工作,当线程数目大于“高水位”时,“线程池”会“清除”多于的线程,以防止溢出。这样程序将始终保持着一定数量的线程在工作,“线程池”特别适用客户端/服务器结构,可以很好地保护服务器的资源。QNX提供了专门的程序库来管理“线程池”头文件是,相应的API主要有:thread_pool_create(),用于建立一个线程池,thread_pool_destroy()程序运行结束后用它来清除线程池,thread_pool_start()用来启动一个线程池。

    5 QNX系统下实用编译方法

    笔者编制了QNX环境下的通用Makefile,用于编译多线程程序,当然也适用于单线程程序的编译,而这个Makefile稍加改动便可以用于LINUX/UNIX系统中,笔者在RedHat Linux7下试验通过。用法,首先将此Makefile 和所要编译的c/c++程序(支持多个c/c++程序)/头文件放置于一个目录中,在终端上键入make,此Makefile将自动把所有相关源代码连接编译成名为go的可执行文件,要运行编译好的程序,只需在终端上键入./go便可。在终端上键入make clean将把所有的编译产生的临时文件删除,只留下原始文件和make文件,在终端上键入make depend将检查文件的依赖性,源代码如下:

EXECUTABLE=go
LINKCC=$(CC)
#如果用于LINUX/UNIX系统,要求安装可移植线程库,并装入下列函数库
#LIBS=-lm –lpthread -lsocket
#如果用于QNX系统装入下面的函数库
LIBS=-lm –lsocket
#如果编译c++程序将下面gcc改为g++
CC=gcc
CFLAGS=-Wall -g
CXX=g++
CXXFLAGS=$(CFLAGS)
SRCS:=$(wildCard *.c) $(wildcard *.cc) $(wildcard *.C)
OBJS:=$(patsubst %.c,%.o,$(wildcard *.c))
 $(patsubst %.cc,%.o,$(wildcard *.cc))
 $(patsubst %.C,%.o,$(wildcard *.C))
DEPS:=$(patsubst %.o,%.d,$(OBJS))
all:$(EXECUTABLE)
$(EXECUTABLE):$(DEPS) $(OBJS)
 $(LINKCC) $(LDFLAGS) -o $(EXECUTABLE) $(OBJS) $(LIBS)
%.d:%.c
 $(CC) -M $(CPPFLAGS) $< >$@
 $(CC) -M $(CPPFLAGS) $< |sed s/.o/.d/>$@
%.d:%.cc
 $(CXX) -M $(CPPFLAGS) $< >$@ 
 $(CXX) -M $(CPPFLAGS) $< |sed s/.o/.d/>$@
%.d:%.C
 $(CXX) -M $(CPPFLAGS) $< >$@
 $(CXX) -M $(CPPFLAGS) $< |sed s/.o/.d/>$@
clean:
 -rm $(OBJS) $(EXECUTABLE) $(DEPS)
# -rm   ./*.* 如果有一些临时的记录文件无法自动去掉加在这里
depend: $(DEPS)
 @echo "Dependencies are now up-to-date."

    6 总结

    QNX实时操作系统的实时性很好,上下文切换时间、中断延时都非常微小,本身提供了对于多线程技术的强大支持,如果在QNX下使用多线程编程技术来解决大型并发多任务系统的控制调度,其优势是很大的,前景也是很广阔的。



上一页  [1] [2] 


本文关键字:多线程  嵌入式系统-技术单片机-工控设备 - 嵌入式系统-技术

《QNX环境下多线程编程》相关文章>>>