Windows打印驱动框架
Windows的打印驱动从总体架构上来说,包括一个渲染组件和一个配置组件。我们可以回想一下最开始的总体架构图。
渲染组件就是负责将应用程序传来的每一页的绘制命令(GDI命令)转换成打印机用来渲染的命令数据(打印机才能识别的命令)发送到打印机中。
配置组件又包含一个可以让用户进行打选项配置的用户接口组件和一个将打印机的配置和特征传递给应用程序的程序接口。
而相较于Windows的其他硬件设备,比较特殊的情况是,打印机的驱动程序并不直接访问和操纵硬件设备,而是把经过处理的二进制指令流和数据流发送给假脱机系统,由假脱机系统负责在合适的时间将打印数据发送至打印机设备所在的端口,完成打印任务。
而打印机驱动在这里也细分成两个大的框架:GDI框架与XPS框架。
1.2.1、GDI打印驱动程序体系结构
GDI 打印驱动程序由以下2个组件组成:
打印图形DLL:辅助 GDI 绘制打印作业,并将绘制后的数据流传送到打印假脱机程序。
打印接口DLL:为打印配置选项导出一个用户接口,同时导出假脱机可以调用以通知驱动程序与打印相关的系统事件的接口。
渲染组件:打印图形 DLL:【https://msdn.microsoft.com/en-us/library/windows/hardware/ff551757(v=vs.85).aspx】
这里的打印图形DLL其实就是一个渲染组件。打印图形DLL实现Drv为前缀的图形DDI(Device Driver Interface,图形驱动接口)【后面说明】函数,这些函数有如下两个方面的作用:
1)辅助GDI完成打印任务。当一个绘制操作必须以设备指定的方式来绘制或者要执行一些GDI引擎不支持的绘制操作时,打印图形DLL可以提供图形DDI函数来处理那些必须按照特定于设备的方式执行和那些不能由GD绘制引擎单独完成的绘制操作。
2)将绘制后的数据流传送到假脱机系统。打印图形DLL通常以RAW数据类型(包括命令序列)【后面说明】产生一个输出流,假脱机可以通过打印监视器将该输出流传送到打印机硬件。
首先我们来说明什么是图形DDI(Device DriverInterface,图形驱动接口)?GDI是图形引擎,其和图形设备驱动程序之间的接口协议就是设备驱动程序接口(DDI)。需要注意的是,DDI是Device DriverInterface,中文字面意思是设备驱动程序接口,正确的写法其实前面还应该加上图形的英文,这样才没有歧义。图形设备驱动程序一般是内核模式DLL,被加载到内核地址空间。它负责在硬件设备上最终实现用户应用程序的绘制调用。
另外一个需要说明的是RAW数据类型,Windows 打印进程通常支持五种数据类型。最常用的两种数据类型是增强型图元文件 (EMF) 和打印就绪 (RAW)。
EMF,即增强型图元文件,是大多数Windows应用程序的默认数据类型。使用EMF,系统会将要打印的文档更改为比RAW文件更易于移植并通常可以在任意打印机上打印的图元文件格式。
RAW是使用非Windows程序的客户端的默认数据类型。RAW数据类型通知后台处理程序在打印之前不要更改打印作业。使用这种数据类型,准备打印作业的整个过程是在客户端计算机上完成的。RAW数据格式是打印机语言PDL的数据格式。PCL和PostScript都是RAW数据,打印引擎可以直接处理。
EMF(Enhanced MetaFile)和RAW处理方式和功能有所不同。
数据类型设置为EMF时,Windows系统生成一个包含GDI功能调用的打印处理文件,此功能调用生成一个组命令以形成应用程序的对象,在设置文件的读取和传输过程中完成对打印设置文件的解释。因此,EMF数据格式的处理方式能够使返回应用程序的时间加快。
使用RAW数据类型时,在写入设置文件之前,打印任务被传输到驱动程序进行解释,图像处理和数据解包。所以,使用RAW数据格式比使用EMF格式打印速度慢。
配置组件:打印接口DLL【https://msdn.microsoft.com/en-us/library/windows/hardware/ff551764(v=vs.85).aspx】
这个打印接口DLL就是驱动程序架构的配置组件,打印驱动程序通常给用户提供很多可修改打印配置的选项,这些选项可以在每一个要打印的文档中被修改。如打印的份数、双面打印、纸张大小、纸张来源、色彩模式、打印分辨率、方向和缩放等,这些选项可以通过由应用程序所调用的用户接口来实现。
打印接口DLL负责为打印配置选项导出一个用户接口。通过为打印机创建属性表单页来提供这一用户接口。应用程序(如Word等)通过调用由假脱机导出的Win32函数显示这个接口,假脱机系统转而又可以调用由打印接口DLL定义的函数。
打印接口DLL不仅为打印配置选项提供用户接口,还导出一些函数。这些函数被假脱机调用以通知驱动程序与打印相关的系统事件,例如驱动程序的安装和升级、打印机的添加和连接等。
1.2.2、GDI打印驱动的工作模式
打印图形DLL提供的绘制函数是基于特定设备的,取决于硬件的绘制能力来决定其所处的工作模式。这里说的绘制其实就是渲染。包括如下3种情况:
打印图形DLL可以选择全部提供DDI绘制函数(RAW模式);
部分提供DDI绘制函数(回调模式);
不提供DDI绘制函数(EMF模式)。
下图是MSDN上对于GDI框架的说明。
上图说明了应用程序使用GDI创建打印作业时的数据流。数据流传送至打印机硬件之前,并不是打印图形DLL会之后直接传送,而是先返回至假脱机,再由假脱机传送至一个监视器而后同过本地或网络端口传送至打印机硬件。
RAW模式:
在RAW模式下,应用可以直接调用驱动所提供的接口直接生成打印机所能处理的Raw文件并直接通过端口监视器发给物理打印机进行打印。这个驱动可以是微软的通用驱动程序也可以是厂商自己编写的驱动程序。
回调模式:
回调模式下,由应用发起的打印文件的部分可能无法使用GDI本身的API来完成了,但是大部分工作是可以之间生成对应的EMF文件的,小部分文件必须调用DDI的绘制函数来进行,生成Raw文件提交给打印处理器,打印处理器会将其进行处理,比如生成EMF文件,提交给GDI User-Mode Client,然后合并为一个完整的EMF文件,最后提交给打印处理器进行处理。打印处理器会讲EMF文件解析为打印机可以处理的Raw文件,并通过端口监视器发给打印机进行打印。
EMF模式:
在EMF模式中,应用通过调用GDI提供的接口而生成用于打印的通用中间文件(EMF文件)。再由打印假脱机队列服务调用打印机驱动的接口将这个EMF文件解析为打印机可以处理的Raw文件,并通过端口服务发给打印机进行打印。
经过上述的说明,也许有人会产生疑问,为什么生成EMF文件不需要去调用DDI就可以生成EMF文件?简要来说,这是由Windows决定的,EMF文件是通过Windows的GDI函数集来描述图像的。我们可以把EMF文件理解为是GDI的指针或者Metafile。EMF格式里面标记的每个含义或者键值和GDI里面的某一类进行一一对应,当需要解析EMF文件时,只需要读取相应的键值就可以知道相应的GDI图像显示的动作是什么。
同时,还有一个疑问:为什么最后都是生成Raw文件发送到打印机?先说说这得从打印后台打印数据格式说起,一般的打印机后台格式有多种,如RAW、EMF...,但RAW格式是唯一被全部打印机所支持。而且在远程打印中,只有RAW格式是被Windows支持的,这可以在MSDN中查到。另外,如果打印图像,除DIB图像外,部分打印机在采用EMF格式时无法打印,如HP LaserJet 1100。当然,如果采用GDIPLUS技术打印,在400DPI下也是可以正常打印的,但当DPI大于400(具体上限没有测试),图像依然无法打印。
这里出现的DPI指的是显示的分辨率。现在我们通常讲的打印机分辨率是多少 dpi,指的是“在该打印机最高分辨率模式下,每英寸所能打印的最多理论墨点数”。更加合理的对于dpi 的解释是这样的:如果一台打印机的分辨率是4800×1200 dpi,那么意味着在X方向(横向)上,两个墨点最近的距离可以达到1/4800英寸;在Y方向(纵向)上,两个墨点的距离可以达到1/1200英寸。
最后在MSDN上面还有一副关于GDI模式的图:
这幅图表示的是GDI模式下打印驱动位于内核态的工作模型,由于XP以后的打印机驱动都为用户态,内核态的打印机驱动基本不再使用,就不另加说明了。
总结一下:当GDI程序执行打印时,通过调用API来传递GDI绘图指令到绘图引擎,绘图引擎要么和打印驱动一起合作来缓存这些绘制指定到一个EMF文件中,要么直接渲染成一个可打印的图片发送到打印假脱机队列服务spooler中。打印假脱机队列服务Spooler解释EMF文件,并将页面布局和作业控制指令信息插入到数据流中,然后发送这些数据里到序列化、并行化或者网络形式的打印机关联的端口上。
由于打印假脱机队列服务Spooler和打印驱动都是可以被单独取代,所以硬件厂商们可以很容易的增加对新硬件的支持。当需要增加对新款打印机的支持时,通常只需要创建根据微软所提供的打印驱动类型中相关联的数据类型就可以了。
1.2.3、XPSDrv打印驱动程序体系结构
XPSDrv打印驱动程序体系结构基于新一代文档格式XPS。XML PaPer Specification(XML文件规格,简称XPS)。这是一种可直接打印的通用电子文档格式,和PDF一样可以由其他任何格式转化。XPS是Windows内部一个完全可以重复书写的打印子系统,打印机可以根据工作类型的不同来接收这种电子文件,包括Microsoft Publisher和Microsoft Office文件等的文件皆可自由转化为XPS电子文档格式进行打印。
XPS不仅仅是一种文档格式,它还是一种物理存储结构上基于OPC,显示技术上基于WPF技术,并且将它们与打印子系统结合的产物。
如上图所示,一个XPS驱动体系的主要组件包括:
过滤器(Filter);
过滤管道(Filter pipeline);
过滤器管道管理器(Filter Pipeline Manager);
过滤器配置文件(Filter ConfigurationFile);
XPS Spooler Process
WPF应用程序。
其中过滤器(Filter),官方翻译为筛选器,意思差不多。过滤器配置文件和配置模块又称为XPSDrv。相较于 GDI 打印驱动程序体系结构,XPSDrv 打印驱动程序体系结构采用了过滤器的方式,可以提供更具弹性的打印途径。XPS 打印机驱动程序 (XPSDrv) 过滤器管道设计用于启用直接和可缩放的XPS文档打印。
首先由应用程序发出打印请求,如果发出的请求是WPF形式的打印请求那么就将进入XPS交换流管道Spooler Process。XPSDrv是XPS打印管道的核心,它包括一个调用过滤器的打印进程模块的设定文件,描述了打印驱动是如何被加载调用的,以及不同的过滤器之间的数据是如何通信的。(这部分在XPSDrv里叫做IFC)。另外图中Print Pipeline Filter的配置文件(XML)定义了:过滤器的分类,过滤器的接口以及每个过滤器的输入输出格式。
在图中,打印作业通过WPF,以XPS流文件的格式进入系统驱动,通过驱动的Ul设置,可以配置给过滤器打印时需要的信息来进行打印操作,然后scheduler通知过滤器管道管理器(Filter pipeline manager),下面过滤器管道管理器(Filter pipeline manager)开始按照过滤器配置文件(Filter ConfigurationFile)配置文件来处理这些作业,过滤器管道管理器(Filter pipeline manager)通过调用配置文件来创建过滤管道(Filter pipeline),当过滤管道(Filter pipeline)被创建完成和初始化后,滤器管道管理器(Filter pipeline manager)就打开过滤管道(Filter pipeline)读取XPS流文件的内容。同时,在各个过滤器之间,使用Stream或Doculnent类型进行数据交换。XPS文件流通过WPF形式传送给Spooler,同时在不同的过滤器之间通过一个XML配置文件进行管理,Ul可以通过DevMode写入Prinit Ticket从而对驱动过滤器进行设置控制。最终,文件通过CsxPStops这个过滤器转化为目前大部分打印机可识别的PS或PCL语言,最后通过打印流接口,将PDL数据交付打印机打印。
1.2.4、XPSDrv打印驱动的工作模式
下图描述了打印子系统(XPSDrv)的工作流程,其中,浅蓝色的部分是Microsoft 提供的,浅×××的部分是有软件供应商提供的软件和应用程序,×××的是硬件打印机供应商(比如HP)提供的部分。
在XPS框架下,只有XPS一种工作模式。应用程序将不会直接调用驱动,打印的数据都会通过操作系统的XPS服务而生成一个用于打印的通用XPS文件。再由打印假脱机队列服务调用打印机驱动的各种过滤器修改生成的XPS文件并最终生成打印机可以处理的文件(可以是XPS文件,也可以是Raw文件),再通过端口监视器发给打印机进行打印。而XPS驱动体系为了兼容以前的系统,提供了两条印刷路径:一条是通过将XPS转化为传统的EMF文件流,再通过传统的GDI印刷路径打印;而另一种打印路径是XPS文件通过一系列过滤器过滤,最后生成打印机能识别的PDL格式文件。这样既可以在新版本的操作系统环境下使用原有的打印技术,也可以在XP操作系统里用XPS打印路径。XPSDrv模型里提供从 XPS到GDI格式的转换器,用来实现Win32应用程序能够打印XPS文档。如果说WPF应用程序在进行写操作的目标打印队列没有XPSDrv驱动程序,那么该转换器就会自动完成从XPS到GDI格式的转换。
1.2.5、总结
下图分别展现了GDI驱动体系和XPS驱动体系的工作流程图:
接下来我们需要看看Windows系统上都有哪些打印机的驱动。目前Windows Server 2012上拥有以下打印机驱动程序:
V4打印机驱动程序(V4 Printer Driver)
对于OpenXPS驱动程序支持
XPS打印机驱动程序(XPSDrv)
微软通用打印机驱动程序(Microsoft UniversalPrinter Driver)
微软PostScript打印机驱动程序(Microsoft PostScriptPrinter Driver)
微软绘图仪驱动程序(Microsoft PlotterDriver)
V4版本的驱动程序框架主要在WindowServer 2012和Windows 8上出现,但是现在基于这样的打印机以及打印驱动还不是市场的主流,相信进过一段时间的推广和发展,今后我们就看V4版本的驱动框架了。
转载于:https://blog.51cto.com/tasnrh/1851867