Windows打印體系結構之Print Spooler概念與架構


Windows打印體系結構之Print Spooler概念與架構
Windows

思傑之路(陶菘) · 2016-09-06 22:07

房子好不好,對我而言始終都是肉體的棲居。對於靈魂,我從來不知道該去向何處。

 
1、Windows打印體系結構

首先附上查找Windows打印相關內容的鏈接,這個分類下包含了Windows打印的方方面面:
https://msdn.microsoft.com/en-us/library/windows/hardware/ff551767(v=vs.85).aspx

如上圖所示,Windows的打印體系結構是由一個打印機假脫機程序(Spooler)和一系列的打印驅動組成。其中帶方框的部分都是可以編寫安裝的。其中的打印驅動程序是指微軟的統一驅動,也就是系統默認的驅動,而迷你驅動就是在此基礎上進行個性化定制。
迷你驅動包括GPD文件和資源DLL,GPD文件就是一個腳本,定義了“打印機首選項”中將出現那些設置,有哪些選項可選,資源DLL就是一個僅僅包含Resource的DLL,提供給GPD使用其中的資源。
而在打印假脫機中:
打印處理器(也就是打印機驅動程序)負責SPL文件操作 EMF/RAW文件操作等;
Render-Plugin則可以對渲染繪制過程進行特殊的處理;
UI-Plugin 就是在“打印機首選項”中定義一些特殊的設置頁面。
語言監視器以及端口監視器和網絡打印提供者我們在打印假脫機中進行介紹。
1.1、打印機假脫機程序(Spooler)

1.1.1、打印假脫機的概念

打印假脫機程序在Windows系統中主要表現就是Windows后台打印程序Print Spooler (Spoolsv.exe)。那么什么是打印假脫機程序(Spooler)呢?顧名思義,我們只需要明白“假脫機”的概念,基本上就明白了什么是打印假脫機程序(Spooler)。
在幾乎所有的操作系統中,外部設備與系統交互都存在兩種模式:聯機模式和脫機模式。
所謂聯機模式是指系統完全按照外部設備的執行順序執行設備操作,再者外部設備往往都是搶占式設備,當一個進程需要使用外部設備時往往要等其它進程使用完畢才可以進行使用。例如:聯機模式下當進程有輸入/輸出需求時就只能在輸入/輸出設備空閑時才能使用設備,如果當前該設備正在被占用,則該進程就只能等待調用者調用結束才能獲取設備使用權,所以聯機模式最大的缺點就是進程之間不能"並發"地使用設備。
而脫機模式正好與聯機模式相反,脫機模式中提出一個概念就是緩沖區的概念,例如:在脫機模式下,當進程需要輸出數據到外部設備時,首先將數據輸出到緩沖區內,然后外部設備再從緩沖區獲取需要輸出的數據。這樣做很好遙免了聯機模式下進程間不能並發的問題。但是脫機模式很大的一個弊端也凸顯出來,那就是當有數據輸出到緩沖區內時,設備並不是立馬對數據進行輸出處理,而是等待緩沖區滿或者進程需要輸出設備輸出的時候,設備才能啟動並將數據輸出至設備進行處理。這樣做會降低設備處理能力,並且頻繁的啟動設備很容易造成設備損壞。
假脫機系統,顧名思義不是真的脫機,它是假的脫機模式。它的真實含義是在聯機的模式下得到脫機效果。假脫機的最終目標是沿用聯機和脫機的所有優點同時避免聯機和脫機的所有缺點。所以打印機是一個相對來說比較特殊的硬件。不但不同於顯卡這種機箱內的硬件,也不同於鼠標鍵盤等外設。鼠標鍵盤顯示器等都是即時反應的,比如移動一下鼠標操作系統都會立即處理並反應在顯示器上。但打印機不是,打印一個文檔快則幾秒,慢則有數十分鍾。操作系統不可能一直等到打印機處理結束再進行返回。所以,操作系統提供了一個叫Spooler的服務來對各種打印機的任務進行管理。Spooler的服務所提供的這個服務有人也將其稱之為打印池。不管稱呼如何,其技術在操作系統領域中給它的定義是:Spooling技術是一種在多道程序環境下模擬脫機方式控制I/O設備進行輸入輸出的技術。Spooling技術的最終目的是通過系統軟件的方式把只能讓一個用戶獨占的設備變成多用戶多進程共享的設備,這種做法不僅可實現進程可以隨時調用設備也可以提高設備的利用率。因為只有當緩沖區沒有任務的時候設備才會進入休眠狀態,同時還降低了對設備進行休眠和喚醒的操作頻率,延長了設備壽命。
因此在這里我們總結一下打印假脫機程序(Spooler)的作用。
打印假脫機程序由一系列的微軟提供的和可選的渲染組件組成,他們的作用包括:
1、檢測打印任務是在本地打印還是網絡打印。
2、接受GDI和打印驅動為特定類型的打印機所提供的數據流。
3、緩沖繪制數據到文件中。
4、從邏輯打印隊列中選出第一個有效的物理打印機。
5、 將緩沖的數據流(如EMF)轉換成能被打印機硬件所識別的格式(如PCL)。
6、發送打印數據流到打印機硬件中。
7、為假脫機組件和打印機的相關信息維護一個基於注冊表的數據庫,這個數據庫的我們在后面會講到。
 
1.1.2、打印假脫機的架構

說道打印假脫機(Spooler)的架構,我們就不得不提一下Windows的通用圖形接口,否則沒法繼續介紹打印假脫機(Spooler)的架構。
對於現在的主流Windows操作系統,存在着兩個統一的圖形接口:GDI和XPS。GDI是從Windows 95開始就一直支持的通用圖形接口,包括最新的Windows 10。而XPS是從Windows Vista開始,微軟開發的另一個通用圖形接口,其目的是為了替換已經老舊的GDI。但肩負着代替GDI使命的XPS過了多年依然沒達成這一任務,也就造成了今天Windows系統里面GDI和XPS共存並相互兼容的狀態。我們會在后面詳細講解GDI的架構以及XPS的架構。在這里點出主要是便於幫助我們理解打印假脫機(Spooler)的架構。
因為GDI和XPS共存且相互兼容,所以在Windwos的現有模式下,Windows打印假脫機(Spooler)的架構有兩種:基於GDI的打印假脫機(Spooler)的架構和基於XPS的打印假脫機(Spooler)的架構。
我們首先來看基於GDI的打印假脫機(Spooler)的架構。
GDI的打印假脫機(Spooler)主要組成結構如下圖所示:【https://msdn.microsoft.com/en-us/library/windows/hardware/ff551781(v=vs.85).aspx】

應用通過調用GDI函數來創建打印任務,通過調用Winspool.drv提供的API接口,將打印內容路由到PrintProvider中。PrintProvider負責管理本地打印和遠程打印,同時要管理打印任務堆里的啟動、停止和枚舉打印隊列。
下面分別介紹這些組件:
應用
打印應用程序通過調用GDI函數創建一個打印作業。
GDI
GDI是Graphics Device Interface的縮寫,含義是圖形驅動程序接口,是Microsoft設計的一套API,是圖形用戶界面GUI系統的一個重要組成部分:為 Win32應用程序提供與設備無關的圖形編程界面,包括:視頻顯示、打印機、畫圖儀和傳真機。圖形設備接口(GDI)包括用戶模式和內核模式組件。微軟把工作於用戶模式的 GDI 稱為 Win32 GDIAPI,工作於內核模式的GDI稱為GDI 圖形引擎。
在 Windows 操作系統下,絕大多數具備GUI(Graphics User Interface)的應用程序都離不開GDI。利用GDI所提供的眾多函數可以方便地在屏幕、打印機及其它輸出設備上輸出圖形、文本等。GDI的出現使程序員無需關心硬件設備及設備驅動就可以將應用程序的輸出轉化為硬件設備上的輸出,實現了程序開發者與硬件設備的隔離,大大方便了開發工作。
WINSPOOL.DRV
Windows的打印客戶端 (winspool.drv)把打印的APl暴露給用戶應用程序, 用戶應用程序用打印API來查詢打印機、打印任務、改變打印機設置、查詢打印機設置、加載打印機驅動程序用戶界面DLL來顯示打印機具體設置屬性頁和做一些其他的事情。Windows的打印客戶端 (winspool.drv)幫助GDI決定打印任務應該如何處理。對於一般的打印任務,GDI生成EMF文件並把它送到打印池客戶,然后打印客戶用遠程進程調用把打印任務發送給打印系統服務進程spoolsv.exe。
SPOOLSV.EXE
spoolsv.exe是后台打印程序的API服務器。spoolsv.exe打印服務向打印客戶DLL導出RPC (遠程過程調用)接口,用戶應用程序可以用Windows的打印客戶端 (winspool.drv)管理打印機、打印機驅動程序和打印任務。spoolsv.exe打印服務本身是一個小的EXE文件(Spoolsv.exe)。它通過打印路由把大多數調用送到打印機提供者。
Spoolsv.exe打印服務隨着操作系統啟動而啟動。該模塊輸出一個RPC接口到后台處理程序的Win32 API中的服務器端。Spoolsv.exe中的客戶包括WINSPOOL.DRV(本地)和Win32spl.dll(遠程)。該模塊實現一些API函數,但大多數功能的調用由所述路由(SPOOLSS.DLL)的裝置傳遞到打印提供着。
打印路由
打印路由SPOOLSS.DLL,顧名思義就是確定打印提供者在哪兒以及這么到它哪兒!我們使用的打印機有可能是本地打印機,也可能是在網絡中的網絡打印機。Spoolsv.exe打印系統服務使用打印路由(spoolss.dlI)把打印任務提交給打印機提供者,打印機提供者知道該把打印任務送到哪里。
打印路由(spoolss. dlI)的任務非常簡單:就是找出正確的打印機提供者,然后把信息發送過去。它借助系統注冊表中打印機相關的設置,通過打印任務所帶的打印機名或者打印機句柄信息完成這一任務。
打印提供者(Print Provider)
打印提供者負責把打印任務分配給本地或遠程計算機。它也管理打印任務隊列操作,如啟動、停止和任務枚舉。與打印服務進程和打印路由不同,系統中可以有很多打印提供者。
Windows操作系統本身內置有幾個打印提供者:
本地打印機提供者(localspl.dll)。處理本地打印任務或遠程客戶發送到本地機的打印任務。每項打印任務最終都由本地打印機提供者處理,它把打印任務送到打印處理器(后面解釋)。
網絡打印機提供者(win32spl.dll)。把打印任務發送到遠程的網絡打印服務器。
HTTP打印機提供者(inetpp.dll)。把打印任務通過HTTP發送到URL地址進行打印。
其中,硬件打印機的廠商比如HP等,能夠用Windows NT的DDK來編寫它們自己的打印機提供者。
打印處理器【打印驅動程序】
在上述打印提供者里面出現了一個新名稱:打印處理器!打印處理器是專門負責把打印任務的打印文件轉換為打印機可以識別的原數據格式。在這里我們又需要引申出另外的一個話題:打印機控制語言或者說打印機指令集。就如同計算機的硬盤一樣,應用程序需要對硬盤讀寫一個數據,需要將其請求發送給操作系統,操作系統會將其轉發給硬盤的SCSI控制器,硬盤的SCSI控制器將應用程序鎖請求的數據轉換為硬盤能夠理解的SCSI語言或者SCSI指令,然后發送到硬盤執行。
同理,在這里這個打印處理器就類似於硬盤的SCSI控制器。所不同的是,硬盤的SCSI控制器是驅動程序加硬件芯片,也就是軟硬一體,而打印機的這個打印處理器,則是通過Windows的驅動程序來完成的,是一個純軟件的操作,因此在純粹的Windows的EMF格式下的光柵打印,會對系統的資源占用較高。
在打印機市場,使用最廣的打印機指令有:ESC、PCL、PostScdpt指令。其中PCL、PostScdpt指令也被稱為頁面描述語言(PDL,PageDescriptional Language),ESC指令也被稱之為嵌入式語言。這只是打印機語言其中的一種分類方法。這些都是打印機原始指令,大部分原始指令都來自於標准打印數據"EMF"的轉換,但是PCL6標准指令和PostScript指令不能通過轉換標准打印數據獲取,而是直接由打印驅動程序生成,故此PCL6指令打印和PostScript指令無需轉換指令而是直接將指令發送到打印設備,所以這兩種打印指令被為原始打印也叫直接打印。其打印的數據不經過驅動程序的打印處理器進行轉換,而是直接發送到打印機,由打印機設備自己解析這些數據並打印。顯而易見這來兩種打印機語言打印效率就比較高。針對這些打印機語言的介紹我們后面再說。
打印監視器
Windows支持兩種類型的打印監視器:語言監視器和端口監視器。在上述Windows的架構體系中,我們可以看到,打印假脫機程序還包含有一些打印的監視器。打印監視器負責把原始打印數據從打印服務引到正確的端口驅動程序上。
語言監視器,這里的語言是指打印機固件能理解的各種打印機任務語言,如PCL。語言監視器的主要目的是通過雙向通信電纜,在打印服務進程和打印機之間提供全雙工的通信信道。計算機到打印機的數據通道主要用於把打印數據送到打印機,打印機到計算機的返回通道用於提供反饋信息。語言監視器的第二個目的是在打印機數據流中插入控制命令。
而端口監視器則是在打印服務進程和內核模式端口驅動程序之間提供通信途徑,該驅動程序直接存取打印機鏈接的硬件的I/O端口。端口監視器是不能直接對硬件操作。它使用常用的文件 API同內核中的驅動程序通信。端口監視器也負責管理邏輯打印機端口,例如本地計算機的所有COM 和LPT端口。
上述大概說明了基於GDI的打印假脫機(Spooler)主要組成結構。而基於XPS的打印假脫機(Spooler)又是如何的一個組成結構呢?
其實對於XPS的打印假脫機來說,和GDI的唯一區別就是GDI圖形接口換成了XPS圖形接口。在Windows中,程序員所開發的圖形應用程序,要么采用GDI的圖形接口開進行開發,要么采用WPF開發框架,WPF(Windows Presentation Foundation)是 Windows  Vista中引入的新的用戶界面開發框架, 可提供更加絢麗的用戶交互界面.,WPF應用程序僅支持基於 XPS 的打印接口。也就是說,其實是Windows 7以及之后的版本中,大部分新開發的應用程序都是基於WPF開發的,其調用的也是XPS接口。因此對於GDI或XPS來說,是GDI的應用程序就調用GDI的打印接口,是XPS的應用程序就調用XPS的打印接口。同時二者又是可以相互兼容和相互轉換的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM