QNX system architecture 11 - Character I/O

實時操作系統的一個關鍵性需求是高性能字符!/O

字符設備和塊設備的一個重要區別:字符設備包含了字節流序列,串行傳輸;不同於塊設備數據永久存在於介質上,此外字符設備的數據是臨時生成的。

在POSIX和UNIX傳統上,這些字符設備位於OS目錄空間/dev/下。比如一個modem或者終端串口設備存在於

/dev/ser1

PC機上的典型硬件設備包括:

  • serial ports
  • parallel ports
  • text-mode consoles
  • pseudo terminal(ptys)

程序使用標準的open(), close(), read()和write() API函數訪問字符設備。字符設備的其他功能,比如波特率,校驗位,流控等使用其他的函數操作。

因爲系統內存在多個字符設備,所以這些設備使用類似的驅動,庫io-char用來最大化代碼複用。

Figure 45: The io-char module is implemented as a library

如圖中所示,io-char實現爲一個庫。io-char模塊包含了所有支持POSIX語義代碼。同時還包含大量非POSIX但是實時系統需要的功能。因爲這些代碼是公共的庫函數,所有的驅動程序都繼承了庫函數中的功能。

驅動是調用io-char庫的執行進程。操作時,驅動首先調用io-char。驅動本身和其他QNX進程類似,可以運行在不同的優先級上,進程優先級是由被控制的硬件以及client請求服務所決定的。

一旦字符設備運行,增加額外設備消耗的內存是很小的,因爲僅僅實現新驅動數據結構是新加的。


Driver/io-char communication

io-char庫管理應用和設備驅動之間的數據流。io-char和驅動間的數據流通過一組內存隊列關聯到每一個字符設備上。

每個設備有三個隊列,每個隊列實現機制爲FIFO。

Figure 46: Device I/O in the QNX RTOS


接收的數據被驅動放在raw輸入隊列中,僅當應用程序請求數據時,io-char消耗input隊列中的數據。

驅動的中斷處理函數調用io-char中的一個函數把數據添加到隊列中,這確保連續的數據輸入規則並且最小化驅動的職責。

io-char模塊放置輸出數據到設備的output隊列,驅動程序處理這些數據並傳送到設備。每次增加新數據,模塊調用驅動一個可信程序以便驅使驅動操作。因爲使用輸出隊列,io-char爲所有字符設備實現了延遲寫。僅當輸出buffer爲滿時,io-char纔會促使當前進程阻塞在寫操作上。

規範化序列完全由io-char管理,用來處理編輯模式的input數據,這個對立的尺寸決定特定設備可被編輯的最大字符數。

這些隊列的大小是可以用命令行參數配置的。缺省值通常大於硬件最大可處理配置,但是你可以調整這些值:減少系統內存需求;適應不尋常的硬件需求,或者處理不尋常的協議請求。

設備驅動簡單的增加接收數據到raw 輸入隊列,或者消耗和傳輸output隊列數據。io-char模塊決定輸出傳輸何時掛起,接收的數據如何響應等。

Device control

低級設備控制使用devctl()調用實現。

POSIX終端控制函數通過調用devctl()實現:

  • tcgetattr()
  • tcsetattr()
  • tcgetpgrp()
  • tcsetpgrp()
  • tcsendbreak()
  • tcflow()

QNX Neutrino extensions

QNX擴展的終端控制API如下所示:

  • tcdropline()
  • tcinject()

io-char模塊直接使用大部分驅動支持的devctl命令,應用程序通過io-char發送設備特定的devctl()給驅動。

Input modes

每一個設備可以在raw或者edited輸入模式。

Raw input mode

在raw模式,io-char不會對收到的字符進行編輯。這減少了每個字符的處理工作,提供了讀數據的最高性能接口。

全屏程序和串口通信程序是使用字符設備raw模式的例子。

在raw模式,中斷處理函數把接收的字符存入raw input buffer。當一個應用從設備請求數據,它可以標識什麼條件下輸入請求被滿足。直到條件滿足,中斷處理不會通知驅動運行,驅動也不會返回任何數據給應用程序。正常情況下,讀應用阻塞直到至少一個字符可用。

下圖演示了可用條件全集:

Figure 47: Conditions for satisfying an input request

當指定了多個條件,那麼只需條件之一滿足,讀操作即滿足。

  • MIN

當應用程序知道它所期望的字符數時,可以使用MIN。

如果知道每幀數據包含的字符數目,那麼可以使用MIN來等待整幀數據的到達。這明顯的減少了IPC和進程調度。MIN通常和TIME或TIMEOUT一起使用。MIN是POSIX標準的一部分。

  • TIME

條件TIME用於接收流數據,當應用接收流數據並且希望在數據停止和暫停時獲得通知。暫停時間爲1/10ths秒。TIME是POSIX標準的一部分。

  • TIMEOUT

條件TIMEOUT,當應用直到在接收數據超時前需要等待多久時使用。timeout單位是1/10ths秒

任何協議知道期望就收的每幀數據字符數,可以使用TIMEOUT。根據幀大小和波特率可以推算出數據何時到達。TIMEOUT可以用來檢測字符丟失,也可以用在交互式程序中,如果在給定的時間內沒有收到用戶輸入的響應。

TIMEOUT不是POSIX標準的一部分,是一個QNX擴展。

  • FORWARD

條件FORWARD在協議通過特殊幀字符分割時使用。比如,串口鏈路上的TCP/IP協議PPP使用幀字符作爲起始和終結字符。如果和TIMEOUT一起使用,FORWARD可以極大的改善協議實現。協議處理收到的是整幀數據而不是一個個字符。對於丟失幀字符的情況,TIMEOUT和TIME可以用來快速恢復。

這極大的減小了IPC工作負載,導致給定的TCP/IP數據率下,更低的處理器利用率。如果沒有FORWARD字符,實現只能每次讀一個字符。

FORWARD是一個QNX擴展,並不是POSIX標準。

把應用通知推到OS服務提供部件,減少用戶機處理髮生的頻率。這最小化系統中IPC通信量以及應用處理佔用的CPU時間。此外如果應用實現的協議在不同的網絡節點上執行,那麼網絡傳輸的數目也可以最小化。


Edited input mode

在edited模式,io-char在每一個接收字符上執行編輯操作。僅僅當一整行完全輸入後(通常是收到一個回車符),行數據纔會給應用處理。這個操作模式通常canonical,有時也稱爲cooked模式。

大部分非全屏應用運行在edited模式,因爲這允許應用應用每次處理一行數據,而不是檢查每個接收到的字符,直到掃描一個行結束符。

在編輯模式,每個字符被中斷處理函數接收到raw input buffer。不像raw 模式驅動在某些輸入條件滿足時才調度驅動,編輯模式下,每接收到一個字符中斷處理函數都會調度驅動。

這樣做是有兩個原因的。首先,edited模式很少用在高性能通信協議下。第二編輯工作很繁重,並不適合在中斷處理函數中執行。

當驅動運行,io-char中的代碼將檢查字符然後保存到canonical buffer中,來構造一行數據。當一個數據完成並且應用請求輸入,行數據從canonical buffer傳輸到應用程序,傳輸是直接從canonical buffer複製到應用buffer,並沒有經過任何中轉複製。

編輯模式代碼可以正確處理canonical buffer中多個待定的輸入行。並且允許部分行被讀取。如果應用程序僅請求一個字符而實際有10字符的行存在。在這種情況下,下一次讀操作將從上一次留下的數據開始讀取。

io-char模塊提供了提供了一組豐富的編輯能力,包括支持cursor鍵的移動,和修改,插入,刪除字符等

Device subsystem performance

當設備在raw模式下,設備子系統的事件流被設計爲最小化負載,最大化吞吐量。爲了達到這個目標,需要使用如下規則:

  • 中斷處理函數把接收到的數據直接放到內存隊列中,僅當有讀操作阻塞並且讀操作可以滿足,中斷處理函數調度驅動運行。在其他情況下,中斷僅僅直接返回。此外,如果io-char已經運行了,那麼不需要有調度發生,因爲可以觀察到數據已經可用,無需進一步的通知。
  • 當一個讀操作被滿足,驅動從raw input buffer中複製數據到接收buffer中,來直接應答應用進程。最終是數據僅被複制一次。

這些規則,加上OS內部很小的中斷和調度延遲,構成了非常簡潔的模型,符合POSIX並且適合實時需求


Console devices

系統consoles(VGA兼容圖形芯片在文本模式下)通過devc-con或者devc-con-hid驅動管理。video顯示卡以及系統鍵盤合在一起作爲物理console。

devc-con或者devc-con-hid驅動允許多個線程並行執行在物理console上,也就是虛擬consoles。devc-con console驅動進程典型的管理超過一組I/O隊列到io-char,他們表現爲一組字符設備/dev/con1, /dev/con2。從應用程序的角度看,有多個consoles可用。

當然,實際上只有一個物理console,在某個時間,僅有一個虛擬console可以顯示,鍵盤被關聯到當前可見的console

Serial devices

串口通信通道被devc-ser*驅動進程家族管理。這些驅動可以管理多個服務通道並且提供如下字符設備/dev/ser1, /dev/ser2

當devc-ser*被啓動,命令行參數可以標識哪一個以及多少串口被安裝,在PC兼容系統中,一般會有兩個標準的串行端口:com1和com2。devc-ser*驅動直接支持大部分多端口串口卡。

QNX包括各種串口驅動(比如devc-ser8250)。更多的細節,參考參考手冊中的dev-ser*

dev-ser*驅動支持硬件流控

Parallel devices

並行打印端口由devc-par驅動管理。當devc-par被啓動時,命令行參數可以表示哪個並行端口被安裝。

devc-par驅動是一個輸出驅動,所以它沒有raw input或者canonical input隊列。output buffer的尺寸可以通過命令行控制。如果配置了一個較大的尺寸,就相當於軟件print buffer的效果。

pseudo terminal devices(ptys)

pseudo終端是由devc-pty驅動管理的。

devc-pty命令行參數標識了要創建的pseudo terminal數目

僞終端pty是一對字符設備:主設備和從設備。從設備提供的接口是POSIX定義的tty設備接口。當然tty設備代表了硬件設備,pty從設備被另外一個線程通過僞終端的master部分控制它。也就是說,任何寫到master設備的數據被作爲從設備的輸入。反之亦然。實際上所有從終端設備的輸入都來自於僞終端主設備上的用戶進程。

 Ptys一般用來創建僞終端接口程序,比如telent使用TCP/IP提供一個終端會話到遠程系統。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章