《VxWorks7編程指南》筆記(三)——信號機制

目錄

1.信號

2.VxWorks信號配置

3.信號相關的基礎函數

4.隊列信號函數

5.信號事件

6.信號處理函數


1.信號

信號作爲一種操作系統機制,用於處理異常條件並對控制流進行異步通知。在很多方面,信號是一種類似於硬件中斷的軟件機制。爲響應總線錯誤、浮點數異常等,操作系統都會產生對應的信號。信號機制提供了用於產生與管理信號的API。

對於應用程序,信號最適合用於錯誤和異常處理,對於任務間通信則不太適合。常見的使用方式包括:使用信號殺死進程和任務、當定時器到達或當一個消息到達消息隊列,則發送一個信號事件,等等。

爲了與POSIX保持一致,VxWorks提供了63個信號,每個信號都有單獨的信號值以及默認的動作(在signal.h中定義)。NULL signal將使用預留的信號值0。

信號可以在任務到任務或任務到進程之間發送。任務可以選擇接受或忽略一個信號。信號是被接收或被忽略,都取決於信號掩碼(signal mask)的設置情況。在內核中,信號掩碼是任務所特有的,如果沒有任務被設置爲接受某個特定的信號,那麼這個信號將被忽略。在用戶空間中,信號掩碼是進程所特有的。有些信號如SIGKILL和SIGSTOP是不能被忽略的。

爲了響應信號,可以創建並註冊信號處理函數,使得任務可以響應一個特定的信號。

一個內核任務或ISR可以向特定的任務和進程發送信號。在內核中,信號的產生與傳遞過程都是在產生信號的任務上下文或ISR中進行。爲了與POSIX標準保持一致,一個發送給進程的信號,都是由第一個已經設置了可以處理該信號的進程負責。

每個內核任務都有一個與之相關的信號掩碼。信號掩碼決定了任務將接受哪些信號。默認情況下,信號掩碼在初始化時被設置爲不屏蔽任何信號(在內核中不存在掩碼繼承)。可以使用sigprocmask()函數修改掩碼。

在內核中,可以爲一個特定的任務註冊信號處理函數。信號處理函數在接收信號的任務的上下文中執行,並且使用了該任務的執行棧空間。即使任務被阻塞,也會調用信號處理函數。

VxWorks提供了軟件信號機制,其中包括了POSIX函數、UNIX BSD兼容的函數以及VxWorks原生的函數。POSIX兼容的信號接口既包括由POSIX1003.1規定的基本信號接口,也包含了由POSIX1003.1B規定的隊列信號擴展。

此外,非POSIX API提供了內核與用戶應用程序之間的信號。包括taskSigquue()、rtpSigqueue()、rtpTaskSigqueue()、taskKill()、rtpTaskKill()、taskRaise()。

在VxWorks內核中(爲了向後兼容),當類POSIX接口需要使用進程ID作爲其參數時,應該使用任務ID代替。

一個RTP任務(用戶模式)可以向如下目標發送信號:

  • 自己
  • 進程中的其他任何任務
  • 系統中任意進程中的任意任務
  • 父進程
  • 系統中的任何其他進程

一個用戶空間的任務不能像內核任務發送信號,即使該任務是一個公共任務。通常發送給一個進程中的任務的信號,都會導致該進程終止。

與內核空間的信號不同,用戶空間的信號的產生是在發送任務的上下文進行的,但是信號的傳遞過程是在接受任務的上下文中進行。

對於進程而言,信號處理函數作用在整個進程,而不是進程中的某個特定任務。

信號處理是在進程範圍完成的。比如,如果進程中的一個任務註冊了一個信號處理函數,且該任務等待着該信號,那麼發送給給進程的信號將由這個任務負責處理。此外,任何沒有屏蔽這個信號的任務都賤給處理該信號。如果沒有任務等待一個給定的信號,那麼這個信號將在進程中掛起,直到有一個任務可以接收該信號爲止。

每個任務都有一個信號掩碼。信號掩碼決定了該任務可以接受哪些信號。當創建任務時,其信號掩碼將繼承自創建它的任務。如果父進程是一個內核任務(即該進程是從內核中創建),那麼這個任務的信號掩碼將被全部初始化爲非屏蔽狀態,同時也將繼承每個信號的默認動作。後續可以使用sigpromask()函數修改屏蔽狀態與默認動作。

注意:內核進程與實時進程對POSIX信號的處理是不同的。在內核中,一個信號的目標總是一個任務;但是在用戶空間,信號的目標既可以是一個任務,也可以是整個進程。

除了信號之外,VxWorks還通過事件機制提供了其他類型的事件通知機制。信號事件是完全異步的,但VxWorks事件機制則不同。事件機制在發送時是異步的,在接收時是同步的,並且不需要一個信號處理函數。

2.VxWorks信號配置

默認條件下,VxWorks已經包含了基本的信號機制組件(INCLUDE_SIGNALS)。其他組件可以按需添加。

3.信號相關的基礎函數

信號與硬件中斷很像。基礎的信號機制提供了63個信號。

  • 可以使用sigvec()或sigaction()函數爲信號綁定信號處理函數;
  • 可以通過kill()或sigqueue()函數發送一個信號;
  • 可以通過sigpromask()函數屏蔽特定的信號。

某些信號與硬件異常有關。例如,總線錯誤、非法指令、浮點數異常都會觸發特定的信號。

VxWorks也提供POSIX或類BSD的kill()函數,用於向一個任務發送信號。

內核信號函數包括:

VxWorks也提供額外的函數作爲POSIX函數的替補,比如rtpKill(),用於從內核向進程發送信號。

 

用戶層信號函數包括:

4.信號隊列函數

sigqueue()系列函數與kill()系列函數類似,都是用於發送信號。

兩者的區別如下:

  • sigqueue()函數將應用程序指定的值作爲信號的一部分發送。該值可以供信號處理函數使用,其類型爲sigval;信號處理函數將在siginfo_t結構體的si_value成員中獲取到該值。
  • 對於任何任務,sigqueue()函數將把多個信號加入隊列中。與此相反,就算信號處理函數執行之前已經有多個信號到達,kill()函數也僅發送一個信號。

VxWorks中包含了爲應用程序保留的信號,信號值從SIGRTMIN到SIGRTMAX。根據POSIX1003.1標準,由RTSIG_MAX宏設置保留的信號數量(默認爲16)。信號值不是由POSIX規定。爲了滿足可移植性,應該基於SIGRTMIN指定信號的值。所有由sigqueue()函數傳遞的信號都按照數字順序排入隊列,信號值小的信號排在信號值大的信號之前。

POSIX1003.1還引入了其他方法接收信號。sigwaitinfo()函數與sigsuspend()或pause()函數不同,其可以允許應用程序在不註冊處理函數的情況下響應信號:當一個信號可用時,sigwaitinfo()函數將信號的值作爲結果返回,就算已經註冊了一個處理函數也不會觸發它。sigtimedwait()函數也類似,區別在於後者可以設置超時。

基本的POSIX信號隊列函數描述如下。這些函數應該由執行在實時進程中的應用程序中調用。

其他的非POSIX的VxWorks信號隊列函數描述如下。這些函數可以用於將VxWorks5.x內核應用程序移植到RTP中。

5.信號事件

信號事件機制允許一個線程或任務按照信號的方式接受特定事件的通知。

下列函數可以用於爲特定的事件活動註冊信號通知:

  • mq_notify()
  • timer_create()
  • timer_open()
  • aio_read()
  • aio_write()
  • lio_listio()

POSIX 1003.1-2001標準定義了三種信號事件通知類型:

SIGEV_NONE

表明當事件發生時,不需要通知。該類型適用於使用異步I/O輪詢的應用程序。

SIGEV_SIGNAL

表明當事件發生時將產生信號。

SIGEV_THREAD

爲在一個新線程上下文中調用的函數所調用,提供異步通知的回調函數。可以爲進程中的多個線程提供比signal更好的通知方式。VxWorks僅在用戶模式支持該選項。

 

通知類型定義在sigeventCommon.h頭文件的sigevent結構體中。結構體中的一個指針用於註冊信號通知。

6.信號處理函數

相較於作爲一種通用的任務間通信機制,信號更適用於錯誤和異常處理。此外,信號處理函數也應該像ISR一樣對待:在信號處理函數中不應該調用函數,以免導致處理函數阻塞。

因爲信號是異步的,所以當某個特定信號觸發時,很難預測哪些資源是不可用的。

所以,爲了確保萬無一失,應該僅調用如下函數:

 

編寫信號處理函數的注意事項:

(1)在退出前釋放資源

  • 釋放任何已分配的內存
  • 關閉任何已打開的文件
  • 釋放任何互斥資源,如信號量

(2)使任何修改過的數據結構保持正常狀態

(3)對於RTP應用程序,通過一個合適的錯誤返回值修改父進程

(4)對於內核應用程序,使用一個合適的錯誤返回值通知內核

 

信號處理函數與任務之間的互斥操作必須小心管理。

通常,應該在信號處理函數中避免以下操作:

  • 獲取同樣能夠被應用程序中其他任務獲取的互斥資源(如信號量)。這可能導致死鎖;
  • 嘗試修改應用程序中其他任務也可以修改的共享數據內存。這可能破壞數據。
  • 使用longjmp()函數改變任務執行的流程。如果longjmp()用於在信號處理函數中重新初始化一個正在運行的任務,必須確保接收信號的任務沒有使用關鍵資源。例如,一個信號被髮送給一個正在使用malloc()函數進行內存分配的任務,然後信號處理函數調用了longjmp(),這將導致內核進入一個不穩定的狀態。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章