亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? 漫談兼容內核之十八:windows的lpc機制.txt

?? 漫談系統內核內幕 收集得很辛苦 呵呵 大家快下在吧
?? TXT
?? 第 1 頁 / 共 4 頁
字號:
漫談兼容內核之十八:Windows的LPC機制

毛德操

    LPC是“本地過程調用(Local Procedure Call)”的縮寫。所謂“本地過程調用”是與“遠程過程調用”即RPC相對而言的。其實RPC是廣義的,RPC可以發生在不同的主機之間,也可以發生在同一臺主機上,發生在同一臺主機上就是LPC。所以在Unix語境下就沒有LPC這一說,即使發生在同一臺主機上也稱為RPC。在歷史上,RPC是“開放軟件基金會(OSF)”設計和提出的一種用以實現“Unix分布計算環境(Unix DCE)”的標準。實際上,微軟的DCOM技術,就是建立在RPC基礎上的。Win2000的RPC可以采用TCP/IP、SPX、NetBIOS、命名管道、以及“本地”作為底層的通信手段,這“本地”就是LPC。另一方面,Windows是一個帶有許多微內核系統特征的操作系統(盡管它的內核不是微內核),系統中有不少“系統級”的服務進程,例如大家已經熟知的csrss、管理用戶登錄的“本地安全認證服務”進程LSASS等等,用戶進程以及微軟提供的系統工具軟件經常需要調用由這些服務進程提供的服務,這里LPC就起著重要的作用。
    LPC的基礎是一種稱為“端口(Port)”的進程間通信機制,類似于本地的(Unix域的)Socket。這種Port機制提供了面向報文傳遞(message passing)的進程間通信,而LPC則是建立在這個基礎上的高層機制,目的是提供跨進程的過程調用。注意這里所謂“跨進程的過程調用”不同于以前所說的“跨進程操作”。前者是雙方有約定、遵循一定規程的、有控制的服務提供,被調用者在向外提供一些什么服務、即提供哪些函數調用方面是自主的,而后者則可以是在不知不覺之間的被利用、被操縱。前者是良性的,而后者可以是惡性的。
    “Microsoft Windows Internals”書中說LPC是“用于快速報文傳遞的進程間通信機制”。其實這是誤導的,應該說Port才是這樣的進程間通信機制,而LPC是建立在這上面的應用。然而這種說法已經被廣泛接受和采納,都把LPC和Port混淆起來了,所以本文也只好跟著說“Windows的LPC機制”,而實際上要說的則主要是Windows的Port機制。在下面的敘述中,凡說到LPC的地方往往實際上是在說Port,讀者要注意區分。

    端口是一種面向連接的通信機制,通信的雙方需要先建立起“連接”。這種連接一般建立在用戶進程之間。在建立了連接的雙方之間有幾種交換報文的方法:
? l 不帶數據的純報文。
? l 不大于256字節的短報文。
? l 如果是大于256字節的長報文,就要在雙方之間建立兩個共享內存區(Section)。雙方通過共享內存區交換數據,但通過報文進行協調和同步。
    大塊數據之所以要通過共享內存區交換,一來是因為這樣就為用于Port機制的緩沖區設置了一個上限,便于內存管理。而更重要的是提高了效率,因為否則便要在發送端把大塊數據搬入內核空間,又在接收端把大塊數據搬到用戶空間。
    Windows內核為基于端口的進程間通信機制提供了不少系統調用,包括(但并不限于):
[code]? l NtCreatePort()
? l NtCreateWaitablePort()
? l NtListenPort()
? l NtConnectPort()
? l NtAcceptConnectPort()
? l NtCompleteConnectPort()
? l NtRequestPort()
? l NtRequestWaiReplyPort()
? l NtReplyPort()
? l NtReplyWaitReceivePort()
? l NtReplyWaitReceivePortEx()。同上,但是帶有超時控制
? l NtReadRequestData()
? l NtWriteRequestData()
? l NtQueryInformationPort()[/code]

    這么多的系統調用(由此也可見LPC在Windows操作系統中的份量),當然不可能在這里一一加以介紹。本文只是從中揀幾個關鍵而典型的作些介紹。另一方面,由于Port與Socket的相似性,對于兼容內核的開發而言應該比較容易把它嫁接到Socket機制上去。
    值得一提的是,Port在Win32 API界面上是不可見的(實際上甚至LPC也不是直接可見的),而Windows的系統調用界面又不公開。這說明Port只是供微軟“內部使用”的。讀者后面就會看到,Port是一種既包括進程間的數據傳輸,又包括進程間的同步、數據量又可大可小的綜合性的進程間通信機制。這樣,由微軟自己開發的軟件、特別是一些系統工具,當然可以使用這些系統調用、也即利用Port這種功能比較強的進程間通信機制,而第三方開發的軟件可就用不上了。

    端口分“連接端口(connection port)”和“通信端口(communication port)”兩種,各自扮演著不同的角色。連接端口用于連接的建立,通信端口才真正用于雙方的通信。只有服務進程才需要有連接端口,但是通信雙方都需要有通信端口。
    雖然LPC一般發生在進程之間,但是實際參與通信的總是具體的線程,所以在下面的敘述中都以線程作為通信的兩端。
    典型的建立連接和通信的過程如下:
? l 需要建立LPC通信時,其中提供服務的一方、即服務線程首先要通過NtCreatePort()創建一個命名的連接端口、即Port對象。這個對象名應為請求服務的一方、即客戶線程所知。
? l 建立了上述連接端口以后,服務線程應通過NtListenPort()等待接收來自客戶線程的連接請求(服務線程被阻塞)。
? l 客戶線程通過NtConnectPort()創建一個客戶方的無名通信端口,并向上述命名的連接端口發出連接請求(客戶線程被阻塞)。
? l 服務線程收到連接請求(因而被喚醒)以后,如果同意建立連接就通過NtAcceptConnectPort()創建一個服務方的無名通信端口、接受連接、并返回該無名通信端口的Handle。然后再通過NtCompleteConnectPort()喚醒客戶線程。
? l 客戶線程被喚醒,并返回所創建的無名通信端口的Handle。
? l 服務線程另創建一個新的線程,負責為客戶線程提供LPC服務。該線程因企圖從上述通信端口接收報文、等待來自客戶端的服務請求而被阻塞。所以,新創建的線程時LPC服務線程,而原來的服務線程是端口服務進程。
? l 端口服務線程再次調用NtListenPort(),等待來自其它客戶的連接請求。
? l 客戶線程通過NtRequestWaiReplyPort()向對方發送報文,請求得到LPC服務,并因等待回答而被阻塞。
? l 服務端的相應線程、即LPC服務線程因接收到報文而被喚醒,并根據報文內容提供相應的LPC服務。
? l LPC服務線程通過NtReplyPort()向客戶方發送回答報文(一般是計算結果)。客戶線程解除阻塞。
    如果回顧一下Wine進程與服務進程wineserver之間的通信,就可以明白Wine是用命名管道和Socket在模仿Windows的LPC通信,只不過那是在用戶空間的模仿。另一方面,熟悉Socket通信的讀者可以看到,Port與Socket是很相像的。

    先看Port的創建。我們看系統調用NtCreatePort()的代碼:

[code]NTSTATUS STDCALL
NtCreatePort (OUT  PHANDLE            PortHandle,
          IN  POBJECT_ATTRIBUTES    ObjectAttributes,
          IN  ULONG                   MaxConnectInfoLength,
          IN  ULONG                   MaxDataLength,
          IN  ULONG                   MaxPoolUsage)
{
  PEPORT  Port;
  NTSTATUS Status;

  DPRINT("NtCreatePort() Name %x\n", ObjectAttributes->ObjectName->Buffer);

  /* Verify parameters */
  Status = LpcpVerifyCreateParameters (PortHandle, ObjectAttributes,
                     MaxConnectInfoLength, MaxDataLength, MaxPoolUsage);
  . . . . . .

  /* Ask Ob to create the object */
  Status = ObCreateObject (ExGetPreviousMode(), LpcPortObjectType,
               ObjectAttributes, ExGetPreviousMode(),
               NULL, sizeof(EPORT), 0, 0, (PVOID*)&Port);
  . . . . . .

  Status = ObInsertObject ((PVOID)Port, NULL, PORT_ALL_ACCESS,
                                            0, NULL, PortHandle);
  . . . . . .

  Status = LpcpInitializePort (Port, EPORT_TYPE_SERVER_RQST_PORT, NULL);
  Port->MaxConnectInfoLength = PORT_MAX_DATA_LENGTH;
  Port->MaxDataLength = PORT_MAX_MESSAGE_LENGTH;
  Port->MaxPoolUsage = MaxPoolUsage;

  ObDereferenceObject (Port);

  return (Status);
}[/code]

    參數ObjectAttributes、即OBJECT_ATTRIBUTES結構中有個Unicode字符串,那就是對象名,需要在調用NtCreatePort()之前加以設置,這跟創建/打開文件時的文件名設置是一樣的。當然,除對象名以外,ObjectAttributes中還有別的信息,那就不是我們此刻所關心的了。其余參數的作用則不言自明。代碼中的LpcpVerifyCreateParameters()對參數進行合理性檢查,ObCreateObject()和ObInsertObject()就無需多說了,而LpcpInitializePort()主要是對代表著端口的EPORT數據結構進行初始化。EPORT數據結構的定義如下:

[code]typedef struct _EPORT
{
  KSPIN_LOCK     Lock;
  KSEMAPHORE    Semaphore;
  USHORT          Type;
  USHORT          State;
  struct _EPORT      *RequestPort;
  struct _EPORT      *OtherPort;
  ULONG           QueueLength;
  LIST_ENTRY      QueueListHead;
  ULONG           ConnectQueueLength;
  LIST_ENTRY      ConnectQueueListHead;
  ULONG           MaxDataLength;
  ULONG           MaxConnectInfoLength;
  ULONG           MaxPoolUsage;        /* size of NP zone */
} EPORT, * PEPORT;[/code]

    結構中的QueueListHead就是用來接收報文的隊列。ConnectQueueListHead則是用來緩存連接請求的隊列,這是因為一個Port可能會一下子接收到好幾個連接請求。字段Type用來紀錄端口的類型,一共有三種類型:

[code]#define EPORT_TYPE_SERVER_RQST_PORT    (0)
#define EPORT_TYPE_SERVER_COMM_PORT   (1)
#define EPORT_TYPE_CLIENT_COMM_PORT   (2)[/code]

    從上面的代碼中可以看出,NtCreatePort()所創建的是“請求端口”,即類型為EPORT_TYPE_SERVER_RQST_PORT的端口,也就是“連接端口”。
    字段state說明端口的狀態和性質,例如EPORT_WAIT_FOR_CONNECT、EPORT_CONNECTED_CLIENT等等。
    注意每個EPORT結構中都嵌有一個“信號量”結構Semaphore,這就是通信雙方用來實現同步的手段。所以說,Port是集成了數據交換和行為同步的綜合性的進程間通信機制。
    還有個字段OtherPort也值得一說,這是個指針,互相指向已經建立了連接的對方端口。
    LpcpInitializePort()的代碼就不看了。只是要說明一下,端口對象的初始化也包括了對其“信號量”數據結構的初始化,并且信號量的初值是0,而最大值則為最大整數LONG_MAX,所以實際上沒有限制。

    創建了連接端口以后,服務進程就通過NtListenPort()等待連接請求,并因此而被阻塞進入睡眠。

[code]NTSTATUS STDCALL
NtListenPort (IN HANDLE  PortHandle,  IN PLPC_MESSAGE  ConnectMsg)
{
  NTSTATUS Status;

  /* Wait forever for a connection request. */
  for (;;)
  {
     Status = NtReplyWaitReceivePort(PortHandle, NULL, NULL, ConnectMsg);
     /* Accept only LPC_CONNECTION_REQUEST requests. Drop any other message. */
     if (!NT_SUCCESS(Status) ||
              LPC_CONNECTION_REQUEST == ConnectMsg->MessageType)
     {
        DPRINT("Got message (type %x)\n", LPC_CONNECTION_REQUEST);
        break;
     }
     DPRINT("Got message (type %x)\n", ConnectMsg->MessageType);
  }

  return (Status);
}[/code]

    所謂“收聽(Listen)”,就是在一個for循環中反復調用NtReplyWaitReceivePort(),等待接收來自客戶方的報文,直至接收到報文、并且所收到報文的類型為“連接請求”、即LPC_CONNECTION_REQUEST時為止。如果接收到的報文不是連接請求就回過去再等,所以才把它放在無限for循環中。
    NtReplyWaitReceivePort()本來的作用是“發送一個應答報文并等待接收”,但是這里的應答報文指針為NULL,也就是無應答報文可發,這樣就成為只是等待來自客戶方的請求了。另一方面,這個函數是不帶超時(Timeout)的,只要沒有收到客戶方的請求就一直等待下去。

[code][NtListenPort() > NtReplyWaitReceivePort()]

NTSTATUS STDCALL
NtReplyWaitReceivePort (IN HANDLE PortHandle, OUT PULONG PortId,
       IN PLPC_MESSAGE LpcReply, OUT PLPC_MESSAGE LpcMessage)
{
  return(NtReplyWaitReceivePortEx (PortHandle, PortId, LpcReply, LpcMessage, NULL));
}[/code]

    NtReplyWaitReceivePort()是不帶超時的,另一個系統調用NtReplyWaitReceivePortEx()則有超時功能,所以前者是通過后者實現的,只是把(最后那個)參數Timeout設成NULL。

[code][NtListenPort() > NtReplyWaitReceivePort() > NtReplyWaitReceivePortEx()]

NTSTATUS STDCALL
NtReplyWaitReceivePortEx(IN HANDLE PortHandle, OUT PULONG PortId,
        IN PLPC_MESSAGE LpcReply, OUT PLPC_MESSAGE LpcMessage,
        IN PLARGE_INTEGER Timeout)
{
   . . . . . .
  
   if( Port->State == EPORT_DISCONNECTED )
     {
       /* If the port is disconnected, force the timeout to be 0
         so we don't wait for new messages, because there won't be
         any, only try to remove any existing messages */
       Disconnected = TRUE;
       to.QuadPart = 0;
       Timeout = &to;
     }
   else Disconnected = FALSE;

   Status = ObReferenceObjectByHandle(PortHandle, PORT_ALL_ACCESS,
                        LpcPortObjectType, UserMode, (PVOID*)&Port, NULL);
   . . . . . .
   /* Send the reply, only if port is connected */
   if (LpcReply != NULL && !Disconnected)
   {
      Status = EiReplyOrRequestPort(Port->OtherPort, LpcReply, LPC_REPLY, Port);
      KeReleaseSemaphore(&Port->OtherPort->Semaphore,
                          IO_NO_INCREMENT, 1, FALSE);
      . . . . . .
   }
  
   /* Want for a message to be received */
   Status = KeWaitForSingleObject(&Port->Semaphore, UserRequest,
                                      UserMode, FALSE, Timeout);
   if( Status == STATUS_TIMEOUT )
   {
       . . . . . .
   }
   . . . . . .
   /* Dequeue the message */
   KeAcquireSpinLock(&Port->Lock, &oldIrql);
   Request = EiDequeueMessagePort(Port);
   KeReleaseSpinLock(&Port->Lock, oldIrql);

   if (Request->Message.MessageType == LPC_CONNECTION_REQUEST)
   {
       LPC_MESSAGE Header;
       PEPORT_CONNECT_REQUEST_MESSAGE CRequest;

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
91.com视频| 樱桃视频在线观看一区| 91麻豆精品国产综合久久久久久 | 国产精品不卡一区二区三区| 精品va天堂亚洲国产| 日韩精品一区在线| 欧美一级日韩一级| 日韩精品在线一区| 国产日韩欧美精品综合| 国产精品久久久久久久久快鸭| 国产精品午夜免费| 1区2区3区国产精品| 亚洲色图欧洲色图| 亚洲成人av一区| 天堂va蜜桃一区二区三区| 天堂av在线一区| 精品一区二区三区日韩| 紧缚捆绑精品一区二区| 成人深夜在线观看| 色综合久久综合网97色综合 | 亚洲美女少妇撒尿| 亚洲一区在线观看免费| 日本中文字幕一区二区有限公司| 精品一区二区av| 国产aⅴ综合色| 日本韩国精品在线| 91麻豆精品久久久久蜜臀 | 一区二区视频在线| 亚洲图片欧美视频| 蜜臀久久99精品久久久久宅男| 国产一区二区三区美女| 一本久久精品一区二区| 91精品国产综合久久婷婷香蕉 | 欧美精品一区二区三区蜜桃视频| 国产欧美综合在线观看第十页| 国产精品久久久久久亚洲毛片 | 蜜臀精品久久久久久蜜臀 | 日韩精品一区在线观看| 中文字幕乱码一区二区免费| 一区二区三区中文字幕在线观看| 美女脱光内衣内裤视频久久影院| 国产成人亚洲综合色影视 | 伊人一区二区三区| 免费成人在线观看| 97成人超碰视| 欧美videossexotv100| 亚洲天堂网中文字| 九九视频精品免费| 欧美优质美女网站| 久久青草欧美一区二区三区| 亚洲精品视频在线看| 精品一区二区三区香蕉蜜桃| 色婷婷av一区二区三区之一色屋| 精品国产乱码久久久久久牛牛| √…a在线天堂一区| 久久精品国产亚洲一区二区三区| 9i在线看片成人免费| 日韩视频不卡中文| 亚洲自拍偷拍图区| 国产成人免费网站| 91麻豆精品国产| 夜夜嗨av一区二区三区网页| 国模大尺度一区二区三区| 在线观看视频91| 中文字幕av免费专区久久| 久久精品国产久精国产| 欧美自拍偷拍一区| 国产精品区一区二区三区| 日韩av一二三| 欧美日韩精品一区二区天天拍小说| 欧美国产97人人爽人人喊| 欧美aⅴ一区二区三区视频| 在线观看亚洲专区| 中文字幕亚洲成人| 国产一区在线看| 欧美一区二区免费视频| 亚洲亚洲人成综合网络| thepron国产精品| 久久久99精品免费观看不卡| 久久www免费人成看片高清| 欧美日韩国产中文| 亚洲精品视频在线观看网站| 不卡一区在线观看| 国产精品萝li| 国产成人av电影在线观看| 欧美成人一区二区| 日韩在线观看一区二区| 欧美网站大全在线观看| 亚洲精品久久久蜜桃| 972aa.com艺术欧美| 亚洲国产精品v| 丁香啪啪综合成人亚洲小说| 久久人人爽人人爽| 国产一区欧美日韩| 久久精品在线观看| 国产99精品视频| 久久久久久久久久久久久夜| 久久精品av麻豆的观看方式| 91精品国产麻豆国产自产在线 | 极品少妇xxxx精品少妇| 欧美一区二区播放| 蜜桃av一区二区三区| 欧美一区二区三区视频免费| 无码av免费一区二区三区试看 | 日本丶国产丶欧美色综合| 国产精品久久久久久久久快鸭 | 麻豆免费精品视频| 日韩欧美www| 狠狠色丁香久久婷婷综| 久久久久国产精品人| 国产suv精品一区二区883| 国产精品女主播在线观看| 国产91露脸合集magnet| 中文字幕一区三区| 色欧美日韩亚洲| 亚洲午夜久久久久久久久电影网 | 亚洲高清免费视频| 欧美高清你懂得| 久久99精品久久久久久| 国产午夜精品久久久久久久| 成人天堂资源www在线| 国产精品传媒视频| 欧美无砖专区一中文字| 热久久免费视频| 久久久91精品国产一区二区精品| 成人高清视频在线观看| 亚洲午夜免费视频| 日韩欧美一卡二卡| 国产成人精品免费| 亚洲一区成人在线| 日韩美女在线视频| 成人一区二区三区视频在线观看 | 一区二区三区丝袜| 欧美精品 日韩| 国产一区二区三区免费播放| 中文字幕视频一区| 337p亚洲精品色噜噜噜| 国产精品一级黄| 亚洲嫩草精品久久| 日韩午夜激情av| av一二三不卡影片| 日韩在线一二三区| 国产精品久久久久久久久搜平片 | 亚洲午夜精品网| 久久综合成人精品亚洲另类欧美| 91蜜桃婷婷狠狠久久综合9色| 视频一区欧美精品| 亚洲国产精品精华液2区45| 欧美三级日韩三级| 国产成人小视频| 亚洲国产一区二区在线播放| 精品91自产拍在线观看一区| 91看片淫黄大片一级在线观看| 蜜臀av一区二区| 亚洲欧美日韩在线| 久久久久国产精品人| 日韩欧美高清在线| eeuss鲁片一区二区三区在线看 | 337p亚洲精品色噜噜噜| 成人福利在线看| 久久成人麻豆午夜电影| 一区二区三区成人| 国产欧美日韩视频在线观看| 欧美日韩免费电影| 成人黄色a**站在线观看| 蜜臂av日日欢夜夜爽一区| 亚洲人精品午夜| 国产片一区二区| 日韩欧美成人一区| 欧美在线不卡视频| 99麻豆久久久国产精品免费优播| 裸体健美xxxx欧美裸体表演| 亚洲主播在线播放| 国产农村妇女毛片精品久久麻豆| 777午夜精品免费视频| 91久久精品一区二区| 成人永久aaa| 国产一区欧美二区| 久久精品国内一区二区三区| 亚洲成av人在线观看| 亚洲欧美日韩成人高清在线一区| 久久久久久97三级| 精品少妇一区二区三区免费观看| 欧美日韩一区二区在线观看视频| www.av精品| 成人晚上爱看视频| 风间由美中文字幕在线看视频国产欧美 | 国产欧美日韩视频在线观看| 欧美变态tickling挠脚心| 欧美视频一区二区三区在线观看| 91免费在线播放| 91热门视频在线观看| 成人av中文字幕| a级精品国产片在线观看| 国产成人综合网| 国产成人av电影在线观看| 国产麻豆日韩欧美久久| 国产一区二区看久久| 国产在线精品国自产拍免费| 国产永久精品大片wwwapp|