共找到2條詞條名為中間層的結果 展開

中間層

網路協議概念

徠中間層(Middle Tier)也稱作應用程序伺服器層或應用服務層,是用戶介面或 Web 客戶端與資料庫之間的邏輯層。

簡介


中間層(Middle Tier)也稱作應用程序伺服器層或應用服務層,是用戶介面或 Web 客戶端與資料庫之間的邏輯層。典型情況下 Web 伺服器位於該層,業務對象在此實例化。中間層是生成並操作接收信息的業務規則和函數的集合。它們通過業務規則(可以頻繁更改)完成該任務,並由此被封裝到在物理上與應用程序程序邏輯本身相獨立的組件中。

三層網路結構


指的是將數據處理過程分為三部分:第一層是客戶端(用戶界面層),提供用戶與系統的友好訪問;第二層是應用服務層(也叫中間層),專司業務邏輯的實現;第三層是數據源層(數據服務層,資料庫系統),負責數據信息的存儲、訪問及其優化。由於業務邏輯被提取到應用服務層,大大降低了客戶端負擔,因此也成為瘦客戶(Thin Client)結構,三層結構在傳統的二層結構的基礎上增加了應用服務層,將應用邏輯單獨進行處理,從而使得用戶界面與應用邏輯位於不同的平台上,兩者之間的通信協議由系統自行定義。通過這樣的結構設計,使得應用邏輯被所有用戶共享,這是兩層結構應用軟體與三層應用軟體之間最大的區別。三層結構將表示部分和業務邏輯部分按照客戶層和應用服務層相分離,客戶端和應用服務層、應用服務層和資料庫服務層之間的通訊、異構平台之間的數據交換等都可以通過中間件或者相關程序來實現。當資料庫或者應用服務層的業務邏輯改變時,客戶端並不需要改變,反之亦然,大大提高了系統模塊的復用性,縮短開發周期,降低維護費用。以JavaApplet為客戶端,以JavaServlet為中間層的三層網路結構,在實時網路信息平台得到了廣泛的應用。

註冊表常識


1、設備資料庫所在的註冊表健值為: HKLMSYSTEMCurrentControlSetEnum ENUM子項中是一個設備資料庫,在資料庫存放計算機中所有安裝的,並且被系統認識到的設備。所有的用戶(包括管理員)都不能更改ENUM項的內容。這是為了保護操作系統和安裝的設備的完整性。為了更改設備的設置,應該使用“設備管理器”。為了在設備管理器中現實隱藏的,非即插即用的,以及沒有連接到計算機上的所有設備,你應該首先在命令解釋器中敲入命令set DEVMGR_SHOW_NONPRESENT_DEVICES=1,然後啟動設備管理器,就可以在設備管理器中刪除和重新配置這些設備了。
2、硬體設備類所在ntControlSetControlClass Class項下存放硬體設備類的配置信息。在Class項下的每個子項都代表一個設備類,子項的名稱使用“唯一全局標識符(GUI)”,這些標識符存放該設備類的配置信息。在每個類標識符下,還會有以4位數命名的子項,他們代表該設備類里的具體設備,其他的配置數據只應用於該具體設備。如網卡的設備類是{4D36E972-E325-11CE-BFC1-08002BE10318},並假定我們網卡對應的4為數命名子項名為0005。其中HKLMSYSTEMCurrentControlSetClass{4D36E972-E325-11CE-BFC1-08002BE10318}5Linkage 中:Export:代表該設備在設備名字空間輸出的設備名字。RootDevice:代表當前設備的GUID。中間層驅動這裡有兩個GUID,第一個是自己的GUID,第二個是該中間層驅動綁定的下層MINIPORT的GUID。UpperBind:代表上層綁定它的NDIS協議驅動或NDIS中間層驅動。當某個協議驅動綁定該MINIPORT設備時,則這個協議驅動的名字必須出現在UpperBind健值的字元串中,否則不能進行綁定。也就是說,UpperBind健值的字元串決定了那個協議驅動(當然也包括中間層驅動註冊的協議)和當前的MINIPORT設備綁定,即,它決定了NDIS的上下層綁定關係。
註:一般添加中間層驅動后,中間層驅動只插入到真是網卡和相應協議中間,不會插入到虛擬網卡(如安裝虛擬機后虛擬出來的網卡設備)和相應協議中間。
3、驅動程序所在的註冊表健值為: HKLMSYSTEMCurrentControlSetServicesENUM子項 通常如果某個服務下存在ENUM子項,表明該服務是用來控制某個設備或者設備交互的,它的下面存放該設備的實例。用戶不要去試圖修改該子項的內容,因為每次系統啟動時,都會重寫該子項的內容。LINKAGE子項值項Bind 存放該協議所在綁定棧的最低層小埠設備實例(即MINIPORT)。值項Export 存放該服務必須訪問的對象,該對象必須已經安裝在系統中,並且該服務能夠使用。值項Route 指定子項Linkage從那裡獲取綁定數據。Parameters Adapters子項 這裡,我們只解釋中間層驅動中該子項的意義。為此,我們假設當前我們討論的HKLMSYSTEMCurrentControlSetServicesXXXX中的XXXX為中間層驅動。對於中間層驅動,該子項下含有一個子項,是以我們當前中間層驅動綁定的下層MINIPORT設備的GUID命名的,在我的系統中,健值如下:{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}在{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}子項有個健,名稱為UpperBindings,該健的健值是當前中間層驅動的MINIPORT設備名稱,在我的系統中為如下健值:Device {5BF5A311-13E4-4746-8865-339DDD6C73AF}

中間層驅動


在我們的函數NDIS_PROTOCOL_CHARACTERISTICS-> BindAdapterHandler()中,會調用一系列函數(如NdisOpenProtocolConfiguration、NdisReadConfiguration)來訪問註冊表,其實都是訪問ParametersAdapters{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}子項。注意,函數NDIS_PROTOCOL_CHARACTERISTICS-> BindAdapterHandler()的倒數第二個參數是SystemSpecific1,如果我們安裝的是XPASSTHRU,則其具體指的是如下字元串: xfilterParametersAdapters{102454C2-9DB3-42A1-B4CF-6A8B67A516C0} 其中xfilter 是XPASSTHRU的,而{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}在不同的系統中不同。函數NdisOpenProtocolConfiguration()其實只是構造一個查詢註冊表的RTL_QUERY_REGISTRY_TABLE結構(該結構在利用函數RtlQueryRegistryValues()查詢註冊表是使用)。並將這個結構封裝到NDIS_WRAPPER_CONFIGURATION_HANDLE結構中,然後作為NdisOpenProtocolConfiguration()的第二個參數返回。其實NdisOpenProtocolConfiguration()構造的RTL_QUERY_REGISTRY_TABLE結構的含義也就是查詢HKLMSYSTEMCurrentControlSetServices xfilterParametersAdapters{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}下的健值(xfilter 會隨著安裝不同的中間層驅動而不同,{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}在不同的系統中不同,下面均省略這些註釋)。
函數NdisReadConfiguration()有兩個作用,它首先修改在函數NdisOpenProtocolConfiguration()構造的RTL_QUERY_REGISTRY_TABLE結構。也就是在查詢HKLMSYSTEMCurrentControlSetServices xfilterParametersAdapters{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}的基礎上加上了一個健,將其變成HKLMSYSTEMCurrentControlSetServices xfilterParametersAdapters{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}UpperBindings。然後函數NdisReadConfiguration()會調用函數RtlQueryRegistryValues()查詢新構造的這個註冊表,並將結果存儲在調用函數NdisReadConfiguration()時的第二個參數中。在我的系統中,RtlQueryRegistryValues()讀出的這個新構造的這個註冊表的健值是:Device {5BF5A311-13E4-4746-8865-339DDD6C73AF}(後面我們稱為RESULT1),它其實是我們註冊的中間層驅動(XPASSTHRU)的設備輸出(其構造是Device+GUID)。其實我們讀出的這個中間層驅動(XPASSTHRU)的設備(即我們剛才讀出的那個健值RESULT1)只在後面的函數NdisIMInitializeDeviceInstanceEx()中才用得著,並且RESULT1是作為函數NdisIMInitializeDeviceInstanceEx()的第二個參BindAdapterHandler()。我們一旦調用了函數NdisOpenAdapter()綁定了一個下層的MINIPORT,為什麼還要調用函數NdisIMInitializeDeviceInstanceEx()初始化我們中間層驅動自己的MINIPORT(因為函數NdisIMInitializeDeviceInstanceEx()的參數是RESULT1,而RESULT1代表我們中間層驅動的MINIPORT)。為了解釋這個原因,我們先做如下假設。
我們假設我們系統安裝了一個中間層驅動(假設為XPASSTRHU),在上圖中,PROT-IM和MINIPORT-IM分別代表我們中間層驅動的協議驅動程序和小埠驅動程序,PROT-TCPIP代表真正的協議驅動程序,MINIPORT-NIC代表真是網卡的小埠驅動程序。當PROT-TCPIP需要發送數據時,會調用函數NdisSend(),其實它會調用MINIPORT-IM中的發送數據函數,但是MINIPORT-IM和MINIPORT-NIC沒聯繫,按照常規是不能發送數據到MINIPORT-NIC的。但是我們可以看到PROT-IM是可以和MINIPORT-NIC互相發送數據的,所以我們必須將MINIPORT-IM和PROT-IM聯繫起來。另外當MINIPORT-NIC需要將數據提交給PROT-TCPIP時,只能首先將數據提交給PROT-IM,PROT-IM也只能通過MINIPORT-IM才能和PROT-TCPIP聯繫起來。所以必須將PROT-IM和MINIPORT-IM聯繫起來。有人說這兩個東西都是我們中間層驅動註冊得,難道還聯繫不起來嗎?不錯,但是不管怎樣你都得通過你得代碼才能將他們聯繫起來呀!下面我們就介紹聯繫得方法。我們以XPASSTHRU為例,在其函數ProtocolBindAdapter()中,先分配了一個ADAPT結構(這個結構是自己定義的,可根據用戶的需要定義)。當調用函數ProtocolBindAdapter()調用函數NdisOpenAdapter()進行綁定時,是以&Adapt->BindingHandle作為函數NdisOpenAdapter()的第三個參數的,這樣Adapt->BindingHandle就指向了NDIS_OPEN_BLOCK1(注意,調用函數NdisOpenAdapter()時的第三個參數會返回指向綁定以後的NDIS_OPEN_BLOCK指針)。然後函數ProtocolBindAdapter()會調用函數NdisIMInitializeDeviceInstanceEx(),該函數會進一步調用XPASSTHRU的NDIS_MINIPORT_CHARACTERISTICS->InitializeHandler()函數。
徠上面我們討論過,NdisIMInitializeDeviceInstanceEx()中的第二個參數就是XPASSTHRU註冊的小埠驅動的設備實例(即上面的RESULT1)。在函數NdisIMInitializeDeviceInstanceEx()中會根據設備名稱(RESULT1),找到對應的MINIPORT結構,並將其指針作為參數傳遞給NDIS_MINIPORT_CHARACTERISTICS->InitializeHandler()函數(以後簡稱InitializeHandler()函數)。在InitializeHandler()函數中,會進一步將MINIPORT結構指針賦值給ADAPT->MiniportHandle(ADAPT就是上面在函數ProtocolBindAdapter()中分配的那個結構)。這樣數據結構ADAPT中就含有了兩個指針,一個指向NDIS_OPEN_BLOCK1,另一個指向MINIPORT-IM,而NDIS_OPEN_BLOCK1和PROT-IM是密切聯繫的,所以ADAPT就將PROT-IM和MINIPORT-IM緊密的聯繫起來了。另外注意,NDIS_MINIPORT_BLOCK->DeviceContext是指向我們的ADAPT結構的,這個賦值在函數NdisIMInitializeDeviceInstanceEx()中完成。上面談到了也是在函數NdisIMInitializeDeviceInstanceEx()中完成了從ADAPT-> MiniportHandle到MINIPORT的綁定,所以在函數NdisIMInitializeDeviceInstanceEx()中完成了ADAPT和MINIPORT的互相連接(即指針互相指向)。函數InitializeHandler()中可以利用句柄MINIPORT的句柄得到我們的ADAPT結構,具體實現這個功能的函數是NdisIMGetDeviceContext(),這個函數的參數是個NDIS_HANDLE類型,但是在該函數內部,會將這個參數轉換成NDIS_MINIPORT_BLOCK結構,並返回NDIS_MINIPORT_BLOCK->DeviceContext。在函數NdisOpenAdapter()中,除了上面提到的完成了由Adapt->BindingHandle到NDIS_OPEN_BLOCK1的指向外,還完成了我們沒有提到的由NDIS_OPEN_BLOCK1-> ProtocolBindingContext到ADAPT的指向,所以函數NdisOpenAdapter()完成了ADAPT和NDIS_OPEN_BLOCK1的互相連接(即指針互相指向)。