日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁(yè) > > 充電吧
[導(dǎo)讀]完成端口(I/O completion)原理收藏 ?異步過程調(diào)用(apcs)問題:只有發(fā)overlapped請(qǐng)求的線程才可以提供callback函數(shù)(需要一個(gè)特定的線程為一個(gè)特定的I/O請(qǐng)求服務(wù))

完成端口(I/O completion)原理收藏 ?

異步過程調(diào)用(apcs)問題:

只有發(fā)overlapped請(qǐng)求的線程才可以提供callback函數(shù)(需要一個(gè)特定的線程為一個(gè)特定的I/O請(qǐng)求服務(wù))。

完成端口(I/O completion)的優(yōu)點(diǎn):

不會(huì)限制handle個(gè)數(shù),可處理成千上萬(wàn)個(gè)連接。I/O completion port允許一個(gè)線程將一個(gè)請(qǐng)求暫時(shí)保存下來,由另一個(gè)線程為它做實(shí)際服務(wù)。

并發(fā)模型與線程池:

在典型的并發(fā)模型中,服務(wù)器為每一個(gè)客戶端創(chuàng)建一個(gè)線程,如果很多客戶同時(shí)請(qǐng)求,則這些線程都是運(yùn)行的,那么CPU就要一個(gè)個(gè)切換,CPU花費(fèi)了更多的時(shí)間在線程切換,線程確沒得到很多CPU時(shí)間。到底應(yīng)該創(chuàng)建多少個(gè)線程比較合適呢,微軟件幫助文檔上講應(yīng)該是2*CPU個(gè)。但理想條件下最好線程不要切換,而又能象線程池一樣,重復(fù)利用。I/O完成端口就是使用了線程池。

理解與使用:

第一步:

在我們使用完成端口之前,要調(diào)用CreateIoCompletionPort函數(shù)先創(chuàng)建完成端口對(duì)象。

定義如下:
HANDLE CreateIoCompletionPort(
???????????????????????????????? HANDLE FileHandle,
??????????????????????????????? HANDLE ExistingCompletionPort,
?????????????????????????????? DWORD CompletionKey,
?????????????????????????????? DWORD NumberOfConcurrentThreads
);
FileHandle:

文件或設(shè)備的handle, 如果值為INVALID_HANDLE_VALUE則產(chǎn)生一個(gè)沒有和任何文件handle有關(guān)系的port.( 可以用來和完成端口聯(lián)系的各種句柄,文件,套接字)

ExistingCompletionPort:

NULL時(shí)生成一個(gè)新port, 否則handle會(huì)加到此port上。

CompletionKey:

用戶自定義數(shù)值,被交給服務(wù)的線程。GetQueuedCompletionStatus函數(shù)時(shí)我們可以完全得到我們?cè)诖寺?lián)系函數(shù)中的完成鍵(申請(qǐng)的內(nèi)存塊)。在GetQueuedCompletionStatus

中可以完封不動(dòng)的得到這個(gè)內(nèi)存塊,并且使用它。

NumberOfConcurrentThreads:

參數(shù)NumberOfConcurrentThreads用來指定在一個(gè)完成端口上可以并發(fā)的線程數(shù)量。理想的情況是,一個(gè)處理器上只運(yùn)行一個(gè)線程,這樣可以避免線程上下文切換的開銷。如果這個(gè)參數(shù)的值為0,那就是告訴系統(tǒng)線程數(shù)與處理器數(shù)相同。我們可以用下面的代碼來創(chuàng)建I/O完成端口。

隱藏在之創(chuàng)建完成端口的秘密:

1. 創(chuàng)建一個(gè)完成端口

CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, dwNumberOfConcurrentThreads);

2. 設(shè)備列表,完成端口把它同一個(gè)或多個(gè)設(shè)備相關(guān)聯(lián)。

CreateIoCompletionPort(hDevice, hCompPort, dwCompKey, 0) ;

第二步:

根據(jù)處理器個(gè)數(shù),創(chuàng)建cpu*2個(gè)工作線程:

CreateThread(NULL, 0, ServerWorkerThread, CompletionPort,0, &ThreadID))

與此同時(shí),服務(wù)器調(diào)用WSASocket,bind, listen, WSAAccept,之后,調(diào)用

CreateIoCompletionPort((HANDLE) Accept, CompletionPort... )把一個(gè)套接字句柄和一個(gè)完成端口綁定到一起。完成端口又同一個(gè)或多個(gè)設(shè)備相關(guān)聯(lián)著,所以以套接字為基礎(chǔ),投遞發(fā)送和請(qǐng)求,對(duì)I/O處理。接著,可以依賴完成端口,接收有關(guān)I/O操作完成情況的通知。再看程序里:

WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags,

&(PerIoData->Overlapped), NULL)開始調(diào)用,這里象前面講過的一樣,既然是異步I/O,所以WSASend和WSARecv的調(diào)用會(huì)立即返回。

系統(tǒng)處理:

當(dāng)一個(gè)設(shè)備的異步I/O請(qǐng)求完成之后,系統(tǒng)會(huì)檢查該設(shè)備是否關(guān)聯(lián)了一個(gè)完成端口,如果是,系統(tǒng)就向該完成端口的I/O完成隊(duì)列中加入完成的I/O請(qǐng)求列。

然后我們需要從這個(gè)完成隊(duì)列中,取出調(diào)用后的結(jié)果(需要通過一個(gè)Overlapped結(jié)構(gòu)來接收調(diào)用的結(jié)果)。怎么知道這個(gè)隊(duì)列中已經(jīng)有處理后的結(jié)果呢,調(diào)用GetQueuedCompletionStatus函數(shù)。

工作線程與完成端口:

和異步過程調(diào)用不同(在一個(gè)Overlapped I/O完成之后,系統(tǒng)調(diào)用該回調(diào)函數(shù)。OS在有信號(hào)狀態(tài)下(設(shè)備句柄),才會(huì)調(diào)用回調(diào)函數(shù)(可能有很多APCS等待處理了))

GetQueuedCompletionStatus

在工作線程內(nèi)調(diào)用GetQueuedCompletionStatus函數(shù)。

GetQueuedCompletionStatus(

??? HANDLE CompletionPort,

??? LPDWORD lpNumberOfBytesTransferred,

??? LPDWORD lpCompletionKey,

??? LPOVERLAPPED *lpOverlapped,

??? DWORD dwMilliseconds

);

CompletionPort:指出了線程要監(jiān)視哪一個(gè)完成端口。很多服務(wù)應(yīng)用程序只是使用一個(gè)I/O完成端口,所有的I/O請(qǐng)求完成以后的通知都將發(fā)給該端口。

lpNumberOfBytesTransferred:傳輸?shù)臄?shù)據(jù)字節(jié)數(shù)

lpCompletionKey:

完成端口的單句柄數(shù)據(jù)指針,這個(gè)指針將可以得到我們?cè)贑reateIoCompletionPort中申請(qǐng)那片內(nèi)存。

lpOverlapped:

重疊I/O請(qǐng)求結(jié)構(gòu),這個(gè)結(jié)構(gòu)同樣是指向我們?cè)谥丿B請(qǐng)求時(shí)所申請(qǐng)的內(nèi)存塊,同時(shí)和lpCompletionKey,一樣我們也可以利用這個(gè)內(nèi)存塊來存儲(chǔ)我們要保存的任意數(shù)據(jù)。

dwMilliseconds:

等待的最長(zhǎng)時(shí)間(毫秒),如果超時(shí),lpOverlapped被設(shè)為NULL,函數(shù)返回False.

GetQueuedCompletionStatus功能及隱藏的秘密:

GetQueuedCompletionStatus使調(diào)用線程掛起,直到指定的端口的I/O完成隊(duì)列中出現(xiàn)了一項(xiàng)或直到超時(shí)。(I/0完成隊(duì)列中出現(xiàn)了記錄)調(diào)用GetQueuedCompletionStatus時(shí),調(diào)用線程的ID(cpu*2個(gè)線程,每個(gè)ServerWorkerThread的線程ID)就被放入該等待線程隊(duì)列中。

等待線程隊(duì)列很簡(jiǎn)單,只是保存了這些線程的ID。完成端口會(huì)按照后進(jìn)先出的原則將一個(gè)線程隊(duì)列的ID放入到釋放線程列表中。

這樣,I/O完成端口內(nèi)核對(duì)象就知道哪些線程正在等待處理完成的I/O請(qǐng)求。當(dāng)端口的I/O完成隊(duì)列出現(xiàn)一項(xiàng)時(shí),完成端口就喚醒(睡眠狀態(tài)中變?yōu)榭烧{(diào)度狀態(tài))等待線程隊(duì)列中的一個(gè)線程。線程將得到完成I/O項(xiàng)中的信息:傳輸?shù)淖止?jié)數(shù),完成鍵(單句柄數(shù)據(jù)結(jié)構(gòu))和Overlapped結(jié)構(gòu)地址,線程是通過GetQueuedCompletionStatus返回這些信息,等待CPU的調(diào)度。

GetQueuedCompletionStatus返回可能有多種原因,如果傳遞無效完成端口句柄,函數(shù)返回False,GetLastError返回一個(gè)錯(cuò)誤(ERROR_INVALID_HANDLE),如果超時(shí),返回False, GetLastError返回WAIT_TIMEOUT, i/o完成隊(duì)列刪除一項(xiàng),該表項(xiàng)是一個(gè)成功完成的I/O請(qǐng)求,則返回True。

調(diào)用GetQueuedCompletionStatus的線程是后進(jìn)先出的方式喚醒的,比如有4個(gè)線程等待,如果有一個(gè)I/O,最后一個(gè)調(diào)用GetQueuedCompletionStatus的線程被喚醒來處理。處理完之后,再調(diào)用 GetQueuedCompletionStatus進(jìn)入等待線程隊(duì)列中。

深入分析完成端口線程池調(diào)度原理:

假設(shè)我們運(yùn)行在2CPU的機(jī)器上。創(chuàng)建完成端口時(shí)指定2個(gè)并發(fā),創(chuàng)建了4個(gè)工作線程加入線程池中等待完成I/O請(qǐng)求,且完成端口隊(duì)列(先入先出)中有3個(gè)完成I/O的請(qǐng)求的情況:

工作線程運(yùn)行, 創(chuàng)建了4個(gè)工作線程,調(diào)用GetQueuedCompletionStatus時(shí),該調(diào)用線程就進(jìn)入了睡眠狀態(tài),假設(shè)這個(gè)時(shí)候,I/O完成隊(duì)列出現(xiàn)了三項(xiàng),調(diào)用線程的ID就被放入該等待線程隊(duì)列中。

I/O完成端口內(nèi)核對(duì)象(第3個(gè)參數(shù)等級(jí)線程隊(duì)列),因此知道哪些線程正在等待處理完成的I/O請(qǐng)求。當(dāng)端口的I/O完成隊(duì)列出現(xiàn)一項(xiàng)時(shí),完成端口就喚醒(睡眠狀態(tài)中變?yōu)榭烧{(diào)度狀態(tài))等待線程隊(duì)列中的一個(gè)線程(前面講過等待線程隊(duì)列是后進(jìn)先出)。所以線程D將得到完成I/O項(xiàng)中的信息:傳輸?shù)淖止?jié)數(shù),完成鍵(單句柄數(shù)據(jù)結(jié)構(gòu))和Overlapped結(jié)構(gòu)地址,線程是通過GetQueuedCompletionStatus返回這些信息。

在前面我們指定了并發(fā)線程的數(shù)目是2,所以I/O完成端口喚醒2個(gè)線程,線程D和線程C,另兩個(gè)繼續(xù)休眠(線程B,線程A),直到線程D處理完了,發(fā)現(xiàn)表項(xiàng)里還有要處理的,就喚醒同一線程繼續(xù)處理。

線程并發(fā)量:

并發(fā)量限制了與該完成端口相關(guān)聯(lián)的可運(yùn)行線程的數(shù)目, 它類似閥門的作用。 當(dāng)與該完成端口相關(guān)聯(lián)的可運(yùn)行線程的總數(shù)目達(dá)到了該并發(fā)量,系統(tǒng)就會(huì)阻塞任何與該完成端口相關(guān)聯(lián)的后續(xù)線程的執(zhí)行, 直到與該完成端口相關(guān)聯(lián)的可運(yùn)行線程數(shù)目下降到小于該并發(fā)量為止。所以解釋了線程池中的運(yùn)行線程可能會(huì)比設(shè)置的并發(fā)線程多的原因。

它的作用:

最有效的假想是發(fā)生在有完成包在隊(duì)列中等待,而沒有等待被滿足,因?yàn)榇藭r(shí)完成端口達(dá)到了其并發(fā)量的極限。此時(shí),一個(gè)正在運(yùn)行中的線程調(diào)用 GetQueuedCompletionStatus時(shí),它就會(huì)立刻從隊(duì)列中取走該完成包。這樣就不存在著環(huán)境的切換,因?yàn)樵撎幱谶\(yùn)行中的線程就會(huì)連續(xù)不斷地從隊(duì)列中取走完成包,而其他的線程就不能運(yùn)行了。

注意:如果池中的所有線程都在忙,客戶請(qǐng)求就可能拒絕,所以要適當(dāng)調(diào)整這個(gè)參數(shù),獲得最佳性能。

線程并發(fā):D線程掛起,加入暫停線程,醒來后又加入釋放線程隊(duì)列。

線程的安全退出:

PostQueudCompletionStatus函數(shù),我們可以用它發(fā)送一個(gè)自定義的包含了OVERLAPPED成員變量的結(jié)構(gòu)地址,里面包含一個(gè)狀態(tài)變量,當(dāng)狀態(tài)變量為退出標(biāo)志時(shí),線程就執(zhí)行清除動(dòng)作然后退出。

完成端口使用需要注意的地方:

1.在執(zhí)行wsasend和wsarecv操作前,請(qǐng)先將overlapped結(jié)構(gòu)體使用memset進(jìn)行清零。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動(dòng)電源

在工業(yè)自動(dòng)化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動(dòng)力設(shè)備,其驅(qū)動(dòng)電源的性能直接關(guān)系到整個(gè)系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動(dòng)勢(shì)抑制與過流保護(hù)是驅(qū)動(dòng)電源設(shè)計(jì)中至關(guān)重要的兩個(gè)環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動(dòng)性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動(dòng)電源

LED 驅(qū)動(dòng)電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個(gè)照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動(dòng)電源易損壞的問題卻十分常見,不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動(dòng)電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動(dòng)電源的公式,電感內(nèi)電流波動(dòng)大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動(dòng)電源

電動(dòng)汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動(dòng)汽車的核心技術(shù)之一是電機(jī)驅(qū)動(dòng)控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動(dòng)系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動(dòng)汽車的動(dòng)力性能和...

關(guān)鍵字: 電動(dòng)汽車 新能源 驅(qū)動(dòng)電源

在現(xiàn)代城市建設(shè)中,街道及停車場(chǎng)照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢(shì)逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動(dòng)電源 LED

LED通用照明設(shè)計(jì)工程師會(huì)遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動(dòng)電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動(dòng)電源的電磁干擾(EMI)問題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會(huì)影響LED燈具的正常工作,還可能對(duì)周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動(dòng)電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動(dòng)電源

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開關(guān)電源

LED驅(qū)動(dòng)電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動(dòng)LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動(dòng)電源
關(guān)閉