基于实时信号的实时控制软件进程间通信方法研究*
2013-08-10齐文军
齐文军
(91550部队 大连 116021)
1 引言
实时控制软件通常是一个多任务、多作业的实时系统,通常采用共享内存区、消息队列、信号灯等技术实现进程间通信[1~2],已有文献对进程间通信机制进行比较分析[3]以及对进程间信号通信机制进行分析[4],上述研究虽然能够实现进程间信息的传递和共享,但缺少一种在任何时刻都能够实时地知道当前执行什么任务,什么作业,何时执行等命令以及中断信号何时到达等信息的聪明机制。本文根据Tru64 UNIX操作系统中实时信号的功能特性,建立一种在实时控制软件中进程间实时传递信息的聪明的通信机制。
2 实时信号机制分析
2.1 实时信号机制简介[5~6]
信号是进程间通信机制中唯一的异步通信机制。信号机制主要用于产生、传送和处理系统中的各种信号。信号的建立、传送和处理都是由软件实现的,因此信号也称为软中断,信号机制又称为软中断机制。根据实时应用的特点,Tru64UNIX操作系统在实时接口库中引入了软中断机制,利用信号的异步特性来实现进程间的实时通信,为实时软件的设计提供了强有力的支持。
Tru64UNIX操作系统中,POSIX 1003.1b实时接口库强化了实时信号功能,为实时应用程序灵活运用实时信号创造了条件,其不仅增加了用户可定义的实时信号数量,在向进程发信号时,建立了信号排队机制,使得同一信号的多次发送可以加以区分,不会造成信号丢失,使进程能够更快地响应实时信号的发送,并提供了向进程发送实时信号的同时,传送该信号的附加信息功能。
2.2 实时信号屏蔽字分析
为了分析实时信号的传递机制,首先要了解具有多线程的进程地址空间的分配形式,如图1所示。
图1 具有多线程的进程地址空间的分配形式
从图1我们可以看出:1)系统资源是分配给进程的,而不是分配给线程的;2)每一个线程都有自己的寄存器和栈;3)线程共享进程资源。
每个进程都有与每个信号相关的信号屏蔽字,由此屏蔽字来决定哪些信号可以传递给该进程,而哪些信号在传递时将会被阻塞。信号屏蔽字具有继承性,也就是说,当父进程调用fork函数派生子进程时,子进程将继承父进程的信号屏蔽字。信号屏蔽字的每一位代表一个信号,在进程中把信号屏蔽字中的哪一位设置为“1”,说明此屏蔽字所对应的信号可以传递给该进程。在设置信号屏蔽字之前必须先清空信号所在的信号集,否则,将出现段访问错误。因此,与每一个信号相关的信号屏蔽字是分配给进程的系统资源,而不是分配给线程的,进程中的所有线程共享与每一个信号相关的信号屏蔽字。
在实际应用中,经过测试表明对如何利用实时信号来实现进程间同步通信、以及进程中多线程间同步通信有如下结论:
1)只能在主线程中定义、初始化和设置信号屏蔽字。否则,在利用多线程来接收信号时,如果有两个或两个以上的实时信号同时或相隔时间很短到达时,进程就会终止,并会在终端上显示收到的实时信号。
2)如果是利用实时信号实现进程间的同步通信,除了发送队列中信号排队个数和1)中的限制之外,没有其它限制。
2.3 实时信号附加信息分析
Tru64Unix操作系统中的POSIX 1003.1b实时扩充程序设计接口提供了一个新的sigqueue函数,用来实现向指定进程发送一个带有可选数据的实时信号的功能。该函数定义在signal.h头文件中,函数原型为int sigqueue(pid_t pid,int signal,union sigval sval);其中,pid是接收signal信号的接收进程;signal是发送进程所发送的实时信号;sval就是随信号所传递的附加信息,附加信息数据结构为
当传递的信息为整型时使用sival_int变量,传递的信息为指针类型时使用sival_ptr变量。这样,就可以针对该函数的这一特点,通过传递整型或指针型的信息来实现进程间的信息传递。
在利用fork函数派生子进程的时候,若没有使用exec族函数调用其它进程的映像来覆盖此子进程的映像,那么父子进程之间传递附加信息不仅可以是整数类型的而且也可以是指针类型的;若使用exec族函数调用其它进程的映像来覆盖此子进程的映像,那么父子进程之间传递的附加信息只能是整数类型的。
原因是每一个进程都有自己的信号堆栈区,可以用来传递信号所附加的指针信息。在利用fork函数派生子进程的时候,子进程复制了父进程的信号堆栈区。若没有利用exec族函数调用其它进程的映像来覆盖此子进程的映像,此时父子进程具有相同的信号堆栈区,用来传递信号所附加的指针指向相同的地址空间,因此能在父子进程中传递指针类型的信息。如果利用exec族函数调用其它进程的映像来覆盖此子进程的映像,当然信号区也被覆盖。此时父子进程信号堆栈区不同,当然传递附加信息的指针地址也无法确定,因此就无法传递附加的指针信息,只能传递整数类型的附加信息。经上述分析可知,在上述两种情况下进程间都能传递整数类型的附加信息,而传递指针型附加信息是有限制的。
3 实时信号在进程间通信中的应用
根据实时控制软件进程间通信的特点和需求结合实时信号的功能特性,既可以利用不同的信号实现进程间通信,也可以利用同一个信号,通过设置不同的附加信息来实现进程间的通信。本文以整型的附加信息为例简单说明实时信号在实时控制软件中的应用。
在一个Tru64UNIX操作系统[7~8]中的多进程实时应用系统中,假定进程PID1和PID2向进程PID3发送实时信号和附加信息。进程PID1需要向进程PID3发送的实时信号为SIGNAL 1_3(信号值假定为SIGRTMIN+2),随该信号传递的附加信息表示PID1进程的某个事件产生了。而进程PID2需要向进程PID3发送的实时信号为SIGNAL 2_3(信号值假定为SIGRTMIN+3),随该信号传递的附加信息表示PID2进程的某个事件产生了。信号附加信息定义如图2所示:
图2 信号附加信息定义表
通过图2中附加信息定义,当PID1进程接收到实时信号SIGNAL 1_3后,根据附加信息sval.sival_int的值就可以判断出PID1进程中哪一个子信号产生了,进而转向SIGNAL1_3不同的信号处理程序。当PID3进程接收到实时信号SIGNAL2_3后,根据附加信息sval.sival_int的值就可以判断出PID2进程中哪一个控制信号产生了,进而转向SIGNAL2_3不同的信号处理程序。
3.1 实时信号发送功能设计
3.1.1 进程PID1发送信号
在信号发送进程PID1中,PID1利用sigqueue函数向进程PID3发送实时信号SIGNAL1_3。unistd.h头文件必须放在所有代码之前,否则会影响实时性[9~10],其主要代码如下:
3.1.2 进程PID2发送信号
在信号发送进程PID2中,PID2利用sigqueue函数向进程PID3发送实时信号SIGNAL2_3。unistd.h头文件必须放在所有代码之前,否则会影响实时性,其主要代码如下:
3.2 实时信号接收功能设计
信号接收进程PID3进程使用POSIX 1003.1b定义的sigwaitinfo或sigtimedwait函数来接收PID1和PID2进程传来的信号,本文以sigwaitinfo为例接收实时信号,其函数原型为
其中,sigset是PID3进程所定义的接收信号集,内容包含PID1和PID2进程向PID3进程发送的实时信号SIG1_3和SIG2_3,是通过sigaddset函数增加的。info是存放接收的PID1和PID2进程传过来的信息,该变量是一个结构,其中的一个成员为union sigval si_value,si_value同前面讲述的sigqueue函数的第3个参数是一样的,PID1和PID2进程传过来的附加信息就存放在此变量中。
假设PID3进程所定义的接收信号集为sigset_recv_pid1,存放信息的变量为info_recv,则PID3进程接收PID1和PID2进程传来信号,其主要代码如下:
4 与其它进程间通信技术实时性比较
为了验证实时信号在实时控制软件中的实时性和可靠性,在测试平台(Tru64UNIX操作系统,1024M 内存,667MHz CPU两个)上对实时信号和其他进行进程间通讯技术(如管道、消息队列、共享内存),以20HZ的频率在进程间都传递4个字节信息和信号灯是采用给共享区中计数器加1的方法进行48小时测试。测试表明,利用这些进程间通信技术进行通信没有发现数据或信号丢失现象,表明这些技术都是可靠的,在延迟上其测试结果如下:
表1 测试结果统计表(单位:μs)
从表1可以看出,直接从共享区读写数据是最快的,但是为了防止从共享区读出脏数据,一般需要添加有名信号灯等互斥锁来保证进程间数据同步,但其缺少一种灵敏机制,就是无法实时知道何时数据写入或读出;使用实时信号不仅提供了一种灵敏机制,而且其实时行为是有保证的,因此传递小信息量的数据,实时信号无疑是最佳选择。
5 结语
实际应用表明利用实时信号的功能特性为实时控制软件设计的进程间通信的聪明机制,与其它进程间通信技术相比,不仅方法简单方便,而且更加安全可靠,系统的实时性也得到了进一步加强,在实时软件设计中具有广泛的实用价值。实际应用中还可以使用信号与其它进程间通信技术相结合的方法进行信息的传递,增加进程间通信的灵活性和实时性。
[1]郑宗汉.实时系统软件基础[M].北京:清华大学出版社,2002:3560.
[2]寇欣宇,王仲,叶声华.基于多进程的测控系统软件设计及其数据通信[J].计算机工程与应用,2000,36(06):101103.
[3]李小群.进程间通信机制的分析与比较[J].计算机科学,2002,29(11):5861.
[4]王文义.Linux中进程间信号通信机制的分析及其应用[J].计算机工程与应用,2005,41(03):8587.
[5]W.Richard Stevens.UNIX网络编程 第2卷:进程间通信[M].北京:清华大学出版社,2000:240300.
[6]唐靖飚.UNIX平台下C语言高级编程指南[M].北京:中国宇航出版社,2000:3570.
[7]Butenhof,D.R.Programming with POSIX Threads[M].AddisonWesley,1997:200215.
[8]Maurice J.Bach.The Design of the UNIX Operating System[M].Prentice Hall PTR,2000.113131.
[9]Tru64UNIX Compaq C Language Reference Manual[M].Compaq Computer Corporation.August,2000:185190.
[10]Tru64UNIX Guide to the POSIX Threads Library[M].Compaq Computer Corporation,2000:150161.