齊文軍
(91550部隊 大連 116021)
實時控制軟件通常是一個多任務、多作業的實時系統,通常采用共享內存區、消息隊列、信號燈等技術實現進程間通信[1~2],已有文獻對進程間通信機制進行比較分析[3]以及對進程間信號通信機制進行分析[4],上述研究雖然能夠實現進程間信息的傳遞和共享,但缺少一種在任何時刻都能夠實時地知道當前執行什么任務,什么作業,何時執行等命令以及中斷信號何時到達等信息的聰明機制。本文根據Tru64 UNIX操作系統中實時信號的功能特性,建立一種在實時控制軟件中進程間實時傳遞信息的聰明的通信機制。
信號是進程間通信機制中唯一的異步通信機制。信號機制主要用于產生、傳送和處理系統中的各種信號。信號的建立、傳送和處理都是由軟件實現的,因此信號也稱為軟中斷,信號機制又稱為軟中斷機制。根據實時應用的特點,Tru64UNIX操作系統在實時接口庫中引入了軟中斷機制,利用信號的異步特性來實現進程間的實時通信,為實時軟件的設計提供了強有力的支持。
Tru64UNIX操作系統中,POSIX 1003.1b實時接口庫強化了實時信號功能,為實時應用程序靈活運用實時信號創造了條件,其不僅增加了用戶可定義的實時信號數量,在向進程發信號時,建立了信號排隊機制,使得同一信號的多次發送可以加以區分,不會造成信號丟失,使進程能夠更快地響應實時信號的發送,并提供了向進程發送實時信號的同時,傳送該信號的附加信息功能。
為了分析實時信號的傳遞機制,首先要了解具有多線程的進程地址空間的分配形式,如圖1所示。

圖1 具有多線程的進程地址空間的分配形式
從圖1我們可以看出:1)系統資源是分配給進程的,而不是分配給線程的;2)每一個線程都有自己的寄存器和棧;3)線程共享進程資源。
每個進程都有與每個信號相關的信號屏蔽字,由此屏蔽字來決定哪些信號可以傳遞給該進程,而哪些信號在傳遞時將會被阻塞。信號屏蔽字具有繼承性,也就是說,當父進程調用fork函數派生子進程時,子進程將繼承父進程的信號屏蔽字。信號屏蔽字的每一位代表一個信號,在進程中把信號屏蔽字中的哪一位設置為“1”,說明此屏蔽字所對應的信號可以傳遞給該進程。在設置信號屏蔽字之前必須先清空信號所在的信號集,否則,將出現段訪問錯誤。因此,與每一個信號相關的信號屏蔽字是分配給進程的系統資源,而不是分配給線程的,進程中的所有線程共享與每一個信號相關的信號屏蔽字。
在實際應用中,經過測試表明對如何利用實時信號來實現進程間同步通信、以及進程中多線程間同步通信有如下結論:
1)只能在主線程中定義、初始化和設置信號屏蔽字。否則,在利用多線程來接收信號時,如果有兩個或兩個以上的實時信號同時或相隔時間很短到達時,進程就會終止,并會在終端上顯示收到的實時信號。
2)如果是利用實時信號實現進程間的同步通信,除了發送隊列中信號排隊個數和1)中的限制之外,沒有其它限制。
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族函數調用其它進程的映像來覆蓋此子進程的映像,當然信號區也被覆蓋。此時父子進程信號堆棧區不同,當然傳遞附加信息的指針地址也無法確定,因此就無法傳遞附加的指針信息,只能傳遞整數類型的附加信息。經上述分析可知,在上述兩種情況下進程間都能傳遞整數類型的附加信息,而傳遞指針型附加信息是有限制的。
根據實時控制軟件進程間通信的特點和需求結合實時信號的功能特性,既可以利用不同的信號實現進程間通信,也可以利用同一個信號,通過設置不同的附加信息來實現進程間的通信。本文以整型的附加信息為例簡單說明實時信號在實時控制軟件中的應用。
在一個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.1 進程PID1發送信號
在信號發送進程PID1中,PID1利用sigqueue函數向進程PID3發送實時信號SIGNAL1_3。unistd.h頭文件必須放在所有代碼之前,否則會影響實時性[9~10],其主要代碼如下:

3.1.2 進程PID2發送信號
在信號發送進程PID2中,PID2利用sigqueue函數向進程PID3發送實時信號SIGNAL2_3。unistd.h頭文件必須放在所有代碼之前,否則會影響實時性,其主要代碼如下:

信號接收進程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進程傳來信號,其主要代碼如下:

為了驗證實時信號在實時控制軟件中的實時性和可靠性,在測試平臺(Tru64UNIX操作系統,1024M 內存,667MHz CPU兩個)上對實時信號和其他進行進程間通訊技術(如管道、消息隊列、共享內存),以20HZ的頻率在進程間都傳遞4個字節信息和信號燈是采用給共享區中計數器加1的方法進行48小時測試。測試表明,利用這些進程間通信技術進行通信沒有發現數據或信號丟失現象,表明這些技術都是可靠的,在延遲上其測試結果如下:

表1 測試結果統計表(單位:μs)
從表1可以看出,直接從共享區讀寫數據是最快的,但是為了防止從共享區讀出臟數據,一般需要添加有名信號燈等互斥鎖來保證進程間數據同步,但其缺少一種靈敏機制,就是無法實時知道何時數據寫入或讀出;使用實時信號不僅提供了一種靈敏機制,而且其實時行為是有保證的,因此傳遞小信息量的數據,實時信號無疑是最佳選擇。
實際應用表明利用實時信號的功能特性為實時控制軟件設計的進程間通信的聰明機制,與其它進程間通信技術相比,不僅方法簡單方便,而且更加安全可靠,系統的實時性也得到了進一步加強,在實時軟件設計中具有廣泛的實用價值。實際應用中還可以使用信號與其它進程間通信技術相結合的方法進行信息的傳遞,增加進程間通信的靈活性和實時性。
[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.