999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

基于完成端口模型的應用程序實現

2014-04-04 13:58:29胡東紅杜光海賀偉毛守備
物聯網技術 2014年3期

胡東紅+杜光海+賀偉+毛守備

摘 要:介紹了Windows最復雜的內核對象IOCP(I/O Completion Port 輸入/輸出完成端口)的基本原理。利用完成端口機制,應用程序能夠為數百上千的用戶服務。文章通過完成端口對象指定一定數量的線程,對重疊I/O請求進行管理,從而為已完成的重疊I/O請求提供服務。通過該模型編寫的網絡服務應用程序可以達到較好的性能。

關鍵詞:完成端口;異步I/O;線程池;應用程序

中圖分類號:TP391 文獻標識碼:A 文章編號:2095-1302(2014)03-0060-03

0 引 言

與計算機執行的大多數其他操作相比,設備I/O是其中最慢、最不可預測的操作之一[1]。比如CPU從硬盤文件中讀寫、網絡讀取數據等,每一線程要等待I/O操作完成再執行后續的代碼。讓太多或者太少的服務器線程來處理線程,都可能會導致性能問題[2]。使用異步設備I/O可以將請求交給設備的驅動程序去處理,應用程序的線程可以執行其他有用的任務。這樣可以更好地使用資源并創建出更高效的應用程序。

但是,隨著客戶端請求、退出的增加,會有許多的并發線程并發執行。由于這些線程都是可運行狀態,Windows內核會浪費太多時間來進行活動線程的上下文切換,如不斷新建和銷毀線程。Windows提供了I/O完成端口機制可以很好地解決上述問題。

1 IOCP模型

當我們創建一個I/O完成端口的時候,系統內核實際上會創建5個不同數據結構。完成端口會將客戶請求加入到一個公共的消息隊列中,然后應用程序會創建一個線程池來處理客戶的請求。當設備與I/O完成端口相關聯后,系統會檢查是否有與設備相關的一個I/O端口,若有則會將已完成的I/O請求追加到消息隊列,并調用相關的工作線程來處理這個請求。當這個請求被處理完后,系統會通過一種機制通知客戶,客戶只需要取處理好的數據即可。圖1所示是一個完成端口模型的結構示意圖。

2 IOCP模型的使用

在實現異步通信機制的時候,一般要用到一個核心數據結構重疊(OVERLAPPED)結構。OVERLAPPED結構定義如下:

typedef struct _OVERLAPPED

{

DWORD Internal;//[out] 保存已處理的I/O請求的錯誤碼

DWORD InternalHigh;//[out] 異步I/O完成保存已傳輸的字節數

DWORD Offset;//[int] 文件傳送的字節偏移量的低位字

DWORD OffsetHigh;//[int] 文件傳送的字節偏移量的高位字

HANDLE hEvent;//[in] 指定一個I/O操作完成后觸發的事件

}OVERLAPPED,*LPOVERLAPPED;

OVERLAPPED結構執行兩個重要的功能:第一,它像一把鑰匙,用以識別每一個目前正在進行的overlapped操作,比如在網絡發送和接收數據時,都會用到WSASend()和WSARecv()函數,參數里面都會附帶一個重疊結構,這個重疊結構我們可以理解為一個網絡操作的ID號,通過這個ID號就可以區分是對哪個網絡進行操作了;第二,它在你和系統之間提供了一個共享區域,參數可以在該區域中雙向傳遞。

圖1 完成端口模型

2.1 創建I/O完成端口

在使用這種模型之前,首先要創建一個I/O完成端口對象,用它面向任意數量的設備句柄,管理多個I/O請求,需要調用CreateIoCompletionPort()函數,該函數定義如下:

HANDLE WINAPI CreateIoCompletionPort(

_in HANDLE FileHandle,

_in_opt HANDLE ExistingCompletionPort,

_in ULONG_PTR CompletionKey,

_in DWORD NumberOfConcurrentThreads

);

該函數用于創建一個完成端口對象和將一個句柄同完成端口關聯在一起。在創建一個完成端口時,前三個參數都會忽略,NumberOfConcurrentThreads參數指定允許有多少線程處于可運行狀態。通常給NumberOfConcurrentThreads參數設為0,那么I/O完成端口會使用默認值,也就是允許并發執行的線程數量等于主機的CPU數量,避免額外的上下文切換。代碼如下:

hIOCP=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);

2.2 工作者線程和完成端口

成功創建一個完成端口后,便可開始將套接字句柄和對象關聯到一起。但是在關聯套接字之前,必須創建一個或多個工作者線程,以便在I/O請求投遞完成端口對象后,為完成端口提供服務。應該創建多少個線程?在此要記住一個重點,在調用CreateIoCompletionPort時指定的并發線程數量,與打算創建的線程池線程數量是有區別的。假如在完成端口上創建的工作者線程數量超過指定并發執行的線性數量(這里設為n個),那么系統最多只允許n個線程運行。因為我們隨時都能執行更多的線程,比如調用了函數Sleep或WaitForSingleObject使其處于暫停狀態,就要用另外線程代替。為了充分發揮系統性能,一般設置為CPU的數量乘以2。

2.3 完成端口與重疊I/O

創建好工作者線程后,調用GetQueuedCompletionStatus()函數讓句柄和完成端口相關聯起來,進行I/O請求處理。它將調用線程切換到睡眠狀態,直到指定的完成端口的隊列中出現該請求。如以套接字句柄為基礎,投遞數據發送和接收請求,會掃描完成端口的隊列里是否有網絡通信的請求存在(如讀取數據、發送數據等),一旦發現消息隊列中出現一項的時候,該完成端口會喚醒線性池中的一個線程。這個線程會得到已完成I/O項中的所有信息:

已傳輸的字節數、完成鍵以及OVERLAPPED結構的地址。GetQueuedCompletionStatus()函數定義如下:

BOOL GetQueuedCompletionStatus(

HANDLE CompletionPort, //指定的IOCP,該值由CreateIoCompletionPort函數創建

LPDWORD lpNumberOfBytes, //一次完成后的I/O操作所傳送數據的字節數

PULONG_PTR lpCompletionKey,//當文件I/O操作完成后,用于存放與之關聯的CK(套接字信息結構體指針)

LPOVERLAPPED *lpOverlapped,//為調用IOCP機制所引用的OVERLAPPED結構

DWORD dwMilliseconds,//用于指定調用者等待CP的時間

);

當一個工作者線程從GetQueuedCompletionStatus調用中接收到I/O完成通知后,在lpCompletion和lpOverlapped參數中,會包含一些必要的套接字信息。利用這些信息,可通過完成端口,繼續在一個套接字上進行I/O處理。通過這些參數,可獲得兩種重要的套接字數據類型:單句柄數據以及單I/O操作數據。單I/O操作數據是CompletionKey(完成鍵)參數標識的是某個特定的套接字句柄數據,相當于用一個標志來綁定每一個I/O操作,這樣收到網絡操作完成的通知后,可以通過這個標志來找出返回的數據對應的I/O操作。該標志可以定義如下:

typedef struct _PER_IO_CONTEXT{

OVERLAPPED m_Overlapped; // 每一個重疊I/O

網絡操作都要有一個

SOCKET m_sockAccept; // 這個I/O操作所使用的

Socket,每個連接的都是一樣的

WSABUF m_wsaBuf; //存儲數據的緩沖區,用來給

重疊操作傳遞參數的

char m_szBuffer[MAX_BUFFER_LEN]; // 對應

WSABUF里的緩沖區

OPERATION_TYPE m_OpType; // 標志這個重疊I/

O操作是做什么的,例如Accept/Recv等

} PER_IO_CONTEXT, *PPER_IO_CONTEXT;

該結構關聯了與I/O操作的某些重要數據元素,例如完成I/O操作發送或接受請求的類型m_OpType。每一個I/O操作對應了響應的PER_IO_CONTEXT,我們還要定義單句柄數據來管理句柄上的所有I/O請求,如在Socket上投遞了多個AcceptEx請求,該結構定義如下:

typedef struct _PER_SOCKET_CONTEXT{

SOCKET m_Socket;// 每一個客戶端連接的Socket

SOCKADDR_IN m_ClientAddr;// 這個客戶端的地址

CArray<_PER_IO_CONTEXT*> m_arrayIoContext; // 數組,所有客戶端IO操作的參數,也就是說對于每一個客戶端Socket是可以在上面同時投遞多個IO請求的

} PER_SOCKET_CONTEXT, *PPER_SOCKET_CONTEXT;

2.4 關閉IOCP

調用PostQueuedCompletionStatus函數,向每個工作者線程都發送一個特殊的完成數據包。可以喚醒那些還在等待完成端口但又沒有已完成的I/O請求,每個線程會對GetQueuedCompletionStatus的返回值進行檢查,如果發現應用程序正在終止,那么它就可以進行清理工作并正常的退出。

3 IOCP程序流程

該程序調用高性能特性的AcceptEx函數用來完成端口異步,取消了阻塞方式的Accept調用。我們知道,AcceptEx是在客戶端連入之前就把客戶端的Socket建立好了,而不需要像Accept那樣在客戶端連入之后,再去時間去建立Socket。系統創建一個Socket的開銷是相當高了,用Accept的話,系統可能來不及為更多的并發客戶端現場準備Socket。另外,相比Accept只能阻塞方式建立一個連入接口,而AcceptEx可以同時在完成端口上投遞多個請求。圖2所示是其程序的整體流程圖。

4 結 語

采用I/O完成端口編寫的服務應用程序,經過Process Explorer測試發現當服務器收到3 000個并發線程的時候CPU占有率約為4%,而采用了多個并發線程的客戶端程序CPU占有率約為12%。所以,如果預計到自己的服務器在任何給定的時間,都會為大量I/O請求提供服務,便應考慮使用I/O完成端口模型,從而獲得更好的性能。但是在編寫基于完成端口的服務應用程序時,還應注意重疊操作可確保按照應用程序安排好的順序執行。然而,不能確保從完成端口返回的完成通知也按照上述順序執行。在對數據包有要求的時候,比如傳送大數據的時候,要注意這個順序。

參 考 文 獻

[1] RICHTER J,NASARRE C. Windows 核心編程[M].Fifth Edition,葛子敖,周靖,等,譯.北京:清華大學出版社,2008.

[2] BEVERIDGE J,WIENER R.Wind32多線程程序設計[M].侯捷,譯.武漢:華中科技大學出版社,2006.

[3] ANTHONY Jones, JIM Ohlund. Network programming for Microsoft Windows [M]. 北京: 清華大學出版社,2002.

[4] 周鵬,黃燦,江楠. 完成端口模型的使用與分析[J]. 軟件, 2012(2): 37-38.

[5] 林延君. 局域網企業信息安全系統的設計與實現[D]. 大連:大連理工大學,2006.

已傳輸的字節數、完成鍵以及OVERLAPPED結構的地址。GetQueuedCompletionStatus()函數定義如下:

BOOL GetQueuedCompletionStatus(

HANDLE CompletionPort, //指定的IOCP,該值由CreateIoCompletionPort函數創建

LPDWORD lpNumberOfBytes, //一次完成后的I/O操作所傳送數據的字節數

PULONG_PTR lpCompletionKey,//當文件I/O操作完成后,用于存放與之關聯的CK(套接字信息結構體指針)

LPOVERLAPPED *lpOverlapped,//為調用IOCP機制所引用的OVERLAPPED結構

DWORD dwMilliseconds,//用于指定調用者等待CP的時間

);

當一個工作者線程從GetQueuedCompletionStatus調用中接收到I/O完成通知后,在lpCompletion和lpOverlapped參數中,會包含一些必要的套接字信息。利用這些信息,可通過完成端口,繼續在一個套接字上進行I/O處理。通過這些參數,可獲得兩種重要的套接字數據類型:單句柄數據以及單I/O操作數據。單I/O操作數據是CompletionKey(完成鍵)參數標識的是某個特定的套接字句柄數據,相當于用一個標志來綁定每一個I/O操作,這樣收到網絡操作完成的通知后,可以通過這個標志來找出返回的數據對應的I/O操作。該標志可以定義如下:

typedef struct _PER_IO_CONTEXT{

OVERLAPPED m_Overlapped; // 每一個重疊I/O

網絡操作都要有一個

SOCKET m_sockAccept; // 這個I/O操作所使用的

Socket,每個連接的都是一樣的

WSABUF m_wsaBuf; //存儲數據的緩沖區,用來給

重疊操作傳遞參數的

char m_szBuffer[MAX_BUFFER_LEN]; // 對應

WSABUF里的緩沖區

OPERATION_TYPE m_OpType; // 標志這個重疊I/

O操作是做什么的,例如Accept/Recv等

} PER_IO_CONTEXT, *PPER_IO_CONTEXT;

該結構關聯了與I/O操作的某些重要數據元素,例如完成I/O操作發送或接受請求的類型m_OpType。每一個I/O操作對應了響應的PER_IO_CONTEXT,我們還要定義單句柄數據來管理句柄上的所有I/O請求,如在Socket上投遞了多個AcceptEx請求,該結構定義如下:

typedef struct _PER_SOCKET_CONTEXT{

SOCKET m_Socket;// 每一個客戶端連接的Socket

SOCKADDR_IN m_ClientAddr;// 這個客戶端的地址

CArray<_PER_IO_CONTEXT*> m_arrayIoContext; // 數組,所有客戶端IO操作的參數,也就是說對于每一個客戶端Socket是可以在上面同時投遞多個IO請求的

} PER_SOCKET_CONTEXT, *PPER_SOCKET_CONTEXT;

2.4 關閉IOCP

調用PostQueuedCompletionStatus函數,向每個工作者線程都發送一個特殊的完成數據包。可以喚醒那些還在等待完成端口但又沒有已完成的I/O請求,每個線程會對GetQueuedCompletionStatus的返回值進行檢查,如果發現應用程序正在終止,那么它就可以進行清理工作并正常的退出。

3 IOCP程序流程

該程序調用高性能特性的AcceptEx函數用來完成端口異步,取消了阻塞方式的Accept調用。我們知道,AcceptEx是在客戶端連入之前就把客戶端的Socket建立好了,而不需要像Accept那樣在客戶端連入之后,再去時間去建立Socket。系統創建一個Socket的開銷是相當高了,用Accept的話,系統可能來不及為更多的并發客戶端現場準備Socket。另外,相比Accept只能阻塞方式建立一個連入接口,而AcceptEx可以同時在完成端口上投遞多個請求。圖2所示是其程序的整體流程圖。

4 結 語

采用I/O完成端口編寫的服務應用程序,經過Process Explorer測試發現當服務器收到3 000個并發線程的時候CPU占有率約為4%,而采用了多個并發線程的客戶端程序CPU占有率約為12%。所以,如果預計到自己的服務器在任何給定的時間,都會為大量I/O請求提供服務,便應考慮使用I/O完成端口模型,從而獲得更好的性能。但是在編寫基于完成端口的服務應用程序時,還應注意重疊操作可確保按照應用程序安排好的順序執行。然而,不能確保從完成端口返回的完成通知也按照上述順序執行。在對數據包有要求的時候,比如傳送大數據的時候,要注意這個順序。

參 考 文 獻

[1] RICHTER J,NASARRE C. Windows 核心編程[M].Fifth Edition,葛子敖,周靖,等,譯.北京:清華大學出版社,2008.

[2] BEVERIDGE J,WIENER R.Wind32多線程程序設計[M].侯捷,譯.武漢:華中科技大學出版社,2006.

[3] ANTHONY Jones, JIM Ohlund. Network programming for Microsoft Windows [M]. 北京: 清華大學出版社,2002.

[4] 周鵬,黃燦,江楠. 完成端口模型的使用與分析[J]. 軟件, 2012(2): 37-38.

[5] 林延君. 局域網企業信息安全系統的設計與實現[D]. 大連:大連理工大學,2006.

已傳輸的字節數、完成鍵以及OVERLAPPED結構的地址。GetQueuedCompletionStatus()函數定義如下:

BOOL GetQueuedCompletionStatus(

HANDLE CompletionPort, //指定的IOCP,該值由CreateIoCompletionPort函數創建

LPDWORD lpNumberOfBytes, //一次完成后的I/O操作所傳送數據的字節數

PULONG_PTR lpCompletionKey,//當文件I/O操作完成后,用于存放與之關聯的CK(套接字信息結構體指針)

LPOVERLAPPED *lpOverlapped,//為調用IOCP機制所引用的OVERLAPPED結構

DWORD dwMilliseconds,//用于指定調用者等待CP的時間

);

當一個工作者線程從GetQueuedCompletionStatus調用中接收到I/O完成通知后,在lpCompletion和lpOverlapped參數中,會包含一些必要的套接字信息。利用這些信息,可通過完成端口,繼續在一個套接字上進行I/O處理。通過這些參數,可獲得兩種重要的套接字數據類型:單句柄數據以及單I/O操作數據。單I/O操作數據是CompletionKey(完成鍵)參數標識的是某個特定的套接字句柄數據,相當于用一個標志來綁定每一個I/O操作,這樣收到網絡操作完成的通知后,可以通過這個標志來找出返回的數據對應的I/O操作。該標志可以定義如下:

typedef struct _PER_IO_CONTEXT{

OVERLAPPED m_Overlapped; // 每一個重疊I/O

網絡操作都要有一個

SOCKET m_sockAccept; // 這個I/O操作所使用的

Socket,每個連接的都是一樣的

WSABUF m_wsaBuf; //存儲數據的緩沖區,用來給

重疊操作傳遞參數的

char m_szBuffer[MAX_BUFFER_LEN]; // 對應

WSABUF里的緩沖區

OPERATION_TYPE m_OpType; // 標志這個重疊I/

O操作是做什么的,例如Accept/Recv等

} PER_IO_CONTEXT, *PPER_IO_CONTEXT;

該結構關聯了與I/O操作的某些重要數據元素,例如完成I/O操作發送或接受請求的類型m_OpType。每一個I/O操作對應了響應的PER_IO_CONTEXT,我們還要定義單句柄數據來管理句柄上的所有I/O請求,如在Socket上投遞了多個AcceptEx請求,該結構定義如下:

typedef struct _PER_SOCKET_CONTEXT{

SOCKET m_Socket;// 每一個客戶端連接的Socket

SOCKADDR_IN m_ClientAddr;// 這個客戶端的地址

CArray<_PER_IO_CONTEXT*> m_arrayIoContext; // 數組,所有客戶端IO操作的參數,也就是說對于每一個客戶端Socket是可以在上面同時投遞多個IO請求的

} PER_SOCKET_CONTEXT, *PPER_SOCKET_CONTEXT;

2.4 關閉IOCP

調用PostQueuedCompletionStatus函數,向每個工作者線程都發送一個特殊的完成數據包。可以喚醒那些還在等待完成端口但又沒有已完成的I/O請求,每個線程會對GetQueuedCompletionStatus的返回值進行檢查,如果發現應用程序正在終止,那么它就可以進行清理工作并正常的退出。

3 IOCP程序流程

該程序調用高性能特性的AcceptEx函數用來完成端口異步,取消了阻塞方式的Accept調用。我們知道,AcceptEx是在客戶端連入之前就把客戶端的Socket建立好了,而不需要像Accept那樣在客戶端連入之后,再去時間去建立Socket。系統創建一個Socket的開銷是相當高了,用Accept的話,系統可能來不及為更多的并發客戶端現場準備Socket。另外,相比Accept只能阻塞方式建立一個連入接口,而AcceptEx可以同時在完成端口上投遞多個請求。圖2所示是其程序的整體流程圖。

4 結 語

采用I/O完成端口編寫的服務應用程序,經過Process Explorer測試發現當服務器收到3 000個并發線程的時候CPU占有率約為4%,而采用了多個并發線程的客戶端程序CPU占有率約為12%。所以,如果預計到自己的服務器在任何給定的時間,都會為大量I/O請求提供服務,便應考慮使用I/O完成端口模型,從而獲得更好的性能。但是在編寫基于完成端口的服務應用程序時,還應注意重疊操作可確保按照應用程序安排好的順序執行。然而,不能確保從完成端口返回的完成通知也按照上述順序執行。在對數據包有要求的時候,比如傳送大數據的時候,要注意這個順序。

參 考 文 獻

[1] RICHTER J,NASARRE C. Windows 核心編程[M].Fifth Edition,葛子敖,周靖,等,譯.北京:清華大學出版社,2008.

[2] BEVERIDGE J,WIENER R.Wind32多線程程序設計[M].侯捷,譯.武漢:華中科技大學出版社,2006.

[3] ANTHONY Jones, JIM Ohlund. Network programming for Microsoft Windows [M]. 北京: 清華大學出版社,2002.

[4] 周鵬,黃燦,江楠. 完成端口模型的使用與分析[J]. 軟件, 2012(2): 37-38.

[5] 林延君. 局域網企業信息安全系統的設計與實現[D]. 大連:大連理工大學,2006.

主站蜘蛛池模板: a级高清毛片| www.国产福利| 国产成人AV综合久久| 国产在线拍偷自揄拍精品| 亚洲国产精品国自产拍A| 欧美日韩久久综合| 免费国产一级 片内射老| 国产三级毛片| 高清国产va日韩亚洲免费午夜电影| 久热精品免费| 欧美中文字幕一区二区三区| 国产精品久久国产精麻豆99网站| 激情六月丁香婷婷| 国产网站黄| 99久视频| 欧美日韩国产成人高清视频 | 97se亚洲| 久久精品中文字幕免费| 97青草最新免费精品视频| 亚洲区欧美区| 亚洲国产成人久久精品软件| 中文字幕啪啪| 欧美在线视频a| 日韩欧美91| 无码区日韩专区免费系列 | 国产H片无码不卡在线视频| 免费毛片在线| 亚洲AⅤ波多系列中文字幕| 国产成人综合网在线观看| 亚洲欧美日韩成人高清在线一区| 永久天堂网Av| 成人福利视频网| 在线免费亚洲无码视频| 亚洲精品图区| 亚洲日韩AV无码一区二区三区人 | 亚洲无码四虎黄色网站| 国产精女同一区二区三区久| 亚洲AⅤ永久无码精品毛片| 国产成人超碰无码| 成人免费黄色小视频| 男女男精品视频| 亚洲色图欧美一区| 亚洲国产综合自在线另类| 日本少妇又色又爽又高潮| 三上悠亚精品二区在线观看| 久久综合国产乱子免费| 一本一本大道香蕉久在线播放| 被公侵犯人妻少妇一区二区三区| 91福利一区二区三区| 亚洲精品国产自在现线最新| 国产成a人片在线播放| 亚洲成年人网| 国产产在线精品亚洲aavv| 国内精品自在自线视频香蕉| 亚洲天堂视频在线播放| 日本一区中文字幕最新在线| 国产精品第三页在线看| 中文成人在线视频| 国产欧美网站| 国产精品免费久久久久影院无码| 在线无码av一区二区三区| 国产乱子伦手机在线| 国产91无码福利在线| 九九九九热精品视频| 亚洲日韩国产精品综合在线观看| 亚洲熟妇AV日韩熟妇在线| 欧美三级视频网站| 久久人人97超碰人人澡爱香蕉| 免费无码AV片在线观看中文| 亚洲精品视频免费看| 思思热在线视频精品| 91精品久久久久久无码人妻| 亚洲第一综合天堂另类专| 中文字幕一区二区人妻电影| 欧美黄网在线| 亚洲福利网址| 国产丝袜精品| 91色爱欧美精品www| 亚洲成人网在线播放| 亚洲精品国产成人7777| 久久不卡国产精品无码| 国产又粗又猛又爽|