I/O Completion Ports

本文僅是對(duì)Windows 在線文檔(部分)的翻譯

I/O完成端口為多處理器系統(tǒng)上的異步I/O請(qǐng)求提供了一個(gè)高效的線程模式提针。當(dāng)進(jìn)程創(chuàng)建一個(gè)I/O完成端口時(shí)海雪,系統(tǒng)會(huì)創(chuàng)建相關(guān)的一系列隊(duì)列。結(jié)合一個(gè)預(yù)先初始化的線程池敢伸,進(jìn)程通過(guò)使用完成端口可以更快扯饶,更高效地處理大量并發(fā)的異步I/O請(qǐng)求恒削。

1 I/O完成端口工作流程

CreateIoCompletionPort函數(shù)用于創(chuàng)建I/O完成端口對(duì)象并將一個(gè)或多個(gè)文件句柄關(guān)聯(lián)到該端口上池颈。當(dāng)這些文件句柄上的異步I/O操作完成時(shí),會(huì)以先入先出的順序向該完成端口的I/O完成隊(duì)列壓入一個(gè)完成封包钓丰。這個(gè)機(jī)制的強(qiáng)大之處在于將多個(gè)文件句柄的同步點(diǎn)整合到一個(gè)對(duì)象上躯砰。當(dāng)然,這個(gè)機(jī)制也有其它用武之地携丁。注意琢歇,雖然完成封包以先入先出的順序入隊(duì),但可能以其它順序出隊(duì)梦鉴。

術(shù)語(yǔ)file handle指一個(gè)抽象的重疊I/O設(shè)備李茫,而不僅僅是磁盤上的文件。例如肥橙,可能是一個(gè)網(wǎng)絡(luò)設(shè)備魄宏,TCP套接字,命名管道存筏,或郵件槽宠互。其可以是任何支持重疊I/O的系統(tǒng)對(duì)象。

當(dāng)某文件句柄和完成端口關(guān)聯(lián)后椭坚,除非該文件句柄上的完成封包從完成端口移除或原始操作同步地返回了錯(cuò)誤予跌,否則文件句柄的狀態(tài)不會(huì)更新。線程(由主線程創(chuàng)建的其它線程或主線程自己)使用GetQueuedCompletionStatus函數(shù)等待壓入到完成端口隊(duì)列的完成封包善茎,而不是直接等待異步I/O完成券册。在完成端口上阻塞的線程將以后入先出的順序喚醒,而下一個(gè)完成封包將會(huì)以先入先出的順序從完成端口的I/O完成隊(duì)列中拉取。也就是說(shuō)烁焙,當(dāng)將完成封包分配給線程處理時(shí)略吨,系統(tǒng)會(huì)喚醒最近與該完成端口關(guān)聯(lián)的線程。

在指定的完成端口上不限定調(diào)用GetQueuedCompletionStatus的線程數(shù)考阱。當(dāng)線程第一次調(diào)用GetQueuedCompletionStatus時(shí)翠忠,他將和指定的完成端口關(guān)聯(lián)(等待線程隊(duì)列),一直到以下情況發(fā)生:

  • 線程退出
  • 后續(xù)調(diào)用GetQueuedCompletionStatus時(shí)指定另外的完成端口
  • 關(guān)閉了完成端口

換句話說(shuō)乞榨,一個(gè)線程在同一時(shí)刻最多只能關(guān)聯(lián)一個(gè)完成端口秽之。

當(dāng)有完成封包到達(dá)時(shí),系統(tǒng)首先檢查當(dāng)前有多少與完成端口關(guān)聯(lián)的線程正在運(yùn)行吃既。如果正在運(yùn)行的線程數(shù)小于指定的最大并發(fā)數(shù)考榨,會(huì)喚醒其中一個(gè)線程(最近的那個(gè))以處理完成封包。當(dāng)運(yùn)行的線程完成其處理時(shí)鹦倚,通常會(huì)再次調(diào)用GetQueuedCompletionStatus河质,這時(shí)候,如果完成端口的I/O完成隊(duì)列不為空震叙,它將繼續(xù)處理下一個(gè)完成封包掀鹅,否則線程阻塞,等待完成封包媒楼。

線程可以調(diào)用PostQueuedCompltionStatus函數(shù)向完成端口的I/O完成隊(duì)列添加特殊的完成封包乐尊。這樣完成端口還可被用來(lái)從進(jìn)程的其它線程接收自定義消息。這通常用于告知工作線程某些外部事件划址,如應(yīng)用程序即將終止運(yùn)行扔嵌。

I/O完成端口句柄以及與之關(guān)聯(lián)的文件句柄一起稱之為對(duì)完成端口的引用。只有當(dāng)沒(méi)有引用時(shí)夺颤,完成端口對(duì)象才能被釋放痢缎。因此,為了釋放完成端口對(duì)象及相關(guān)資源世澜,所有這些句柄必須被正確地關(guān)閉独旷。在所有這些條件滿足后,應(yīng)用程序必須調(diào)用CloseHandle關(guān)閉完成端口句柄宜狐。

I/O完成端口和創(chuàng)建它的進(jìn)程關(guān)聯(lián)势告,無(wú)法在進(jìn)程間共享,但是可以被進(jìn)程內(nèi)的線程共享抚恒。

2 線程和并發(fā)

完成端口最重要的屬性是最大并發(fā)數(shù)咱台。完成端口的最大并發(fā)數(shù)在其通過(guò)CreateIoCompletionPort創(chuàng)建時(shí)由NumberOfConcurrentThreads參數(shù)指定。這個(gè)參數(shù)限制與完成端口關(guān)聯(lián)的線程的可運(yùn)行數(shù)俭驮。如果同完成端口關(guān)聯(lián)的正在運(yùn)行的線程數(shù)已達(dá)到指定的最大并發(fā)值回溺,系統(tǒng)將阻止其它關(guān)聯(lián)線程被喚醒春贸,直到正在運(yùn)行的線程數(shù)小于最大并發(fā)數(shù)。

最高效的情形是遗遵,當(dāng)隊(duì)列中有完成封包等待時(shí)萍恕,由于完成端口上正在運(yùn)行的線程數(shù)已達(dá)到其最大并發(fā)數(shù)而不會(huì)喚醒任何其它線程。在這種情況下车要,如果完成端口的隊(duì)列中總是有正在等待的完成封包允粤,當(dāng)正在運(yùn)行的線程處理完上一個(gè)封包,然后調(diào)用GetQueuedCompletionStatus時(shí)翼岁,其不會(huì)阻塞而是立即獲得下一個(gè)完成封包并處理类垫。這時(shí)沒(méi)有線程上下文切換,因?yàn)檫\(yùn)行中的線程是連續(xù)地獲得完成封包的琅坡,同時(shí)其它線程仍然不能運(yùn)行悉患。

在上面的例子中,額外的線程似乎沒(méi)什么用榆俺,因?yàn)樗鼈儚膩?lái)不運(yùn)行售躁。但是上面的情況是假設(shè)運(yùn)行線程從來(lái)不會(huì)因?yàn)槠渌鼨C(jī)制而進(jìn)入等待狀態(tài)。

顯然茴晋,合適的最大并發(fā)數(shù)是機(jī)器的CPU數(shù)陪捷。如果線程處理的事務(wù)需要長(zhǎng)時(shí)間運(yùn)算,更大的并發(fā)數(shù)將允許更多線程得以運(yùn)行晃跺。有些完成封包可能需要較長(zhǎng)的時(shí)間進(jìn)行處理揩局,但多數(shù)完成封包的處理時(shí)間是差不多的∠苹ⅲ可以通過(guò)數(shù)值試驗(yàn)獲取最佳的最大并發(fā)數(shù)。

如果與完成端口關(guān)聯(lián)的正在運(yùn)行的線程因?yàn)槠渌蜻M(jìn)入等待狀態(tài)付枫,例如烹玉,調(diào)用了SuspendThread函數(shù),系統(tǒng)會(huì)允許因調(diào)用GetQueuedCompletionStatus而等待運(yùn)行的線程處理完成封包阐滩。當(dāng)之前進(jìn)入等待的線程又開(kāi)始運(yùn)行時(shí)二打,可能有一個(gè)短暫的時(shí)間實(shí)際運(yùn)行的線程數(shù)大于最大并發(fā)數(shù)。但是系統(tǒng)會(huì)通過(guò)禁止喚醒其它等待線程而快速減小這個(gè)實(shí)際并發(fā)數(shù)掂榔。這就是為什么應(yīng)用程序要將線程池線程數(shù)設(shè)置的比完成端口最大并發(fā)數(shù)大的原因继效。

3 支持函數(shù)

下面的函數(shù)可用于開(kāi)始使用I/O完成端口的I/O操作。必須向函數(shù)傳遞OVERLAPPED結(jié)構(gòu)體實(shí)例且在此之前必須將相關(guān)的文件句柄和完成端口關(guān)聯(lián):

  • ConnectNamedPipe
  • DeviceIoControl
  • LockFileEx
  • ReadDirectoryChangesW
  • ReadFile
  • TransactNamedPipe
  • WaitCommEvent
  • WriteFile
  • WSASendMsg
  • WSASendTo
  • WSARecvFrom
  • WSARecvMsg
  • WSARecv

4 APIs

CreateIoCompletionPort

創(chuàng)建一個(gè)I/O完成端口并將其和指定的文件句柄關(guān)聯(lián)装获,或僅僅是創(chuàng)建一個(gè)完成端口瑞信。
在I/O完成端口上關(guān)聯(lián)一個(gè)打開(kāi)的文件句柄將允許進(jìn)程接收該文件句柄上的異步I/O操作的完成通知。

這里文件句柄是一個(gè)系統(tǒng)抽象的名詞穴豫,其代表一個(gè)重疊I/O端而不是磁盤上的一個(gè)文件凡简。任何支持重疊I/O的系統(tǒng)對(duì)象逼友,如網(wǎng)絡(luò)端點(diǎn)、TCP socket秤涩、命名管道或mail slots都可當(dāng)做文件句柄帜乞。

Syntax

HANDLE WINAPI CreateIoCompletionPort(
    _In_ HANDLE FileHandle,
    _In_opt_ HANDLE ExistingCompletionPort,
    _In_ ULONG_PTR CompletionKey,
    _In_ DWORD NumberOfConcurrentThreads
);

Parameters
FileHandle
一個(gè)打開(kāi)的文件句柄或者是INVALID_HANDLE_VALUE
該句柄必須是支持重疊I/O的對(duì)象筐眷。
如果指定了文件句柄黎烈,其必須以重疊I/O模式打開(kāi)。例如匀谣,必須以FILE_FLAG_OVERLAPPED標(biāo)識(shí)調(diào)用CreateFile函數(shù)以獲得一個(gè)文件句柄怨喘。
如果指定了INVALID_HANDLE_VALUE,函數(shù)將只是創(chuàng)建一個(gè)新的完成端口振定,這種情況下必怜,ExistingCompletionPort必須是NULLCompletionKey會(huì)被忽略。

ExistingCompletionPort
一個(gè)已存在的I/O完成端口句柄或者是NULL后频。
如果指定了一個(gè)已存在的完成端口梳庆,函數(shù)會(huì)將其和參數(shù)FileHandle指定的文件句柄關(guān)聯(lián)。如果函數(shù)執(zhí)行成功返回該完成端口卑惜。
如果該參數(shù)為NULL膏执,函數(shù)將創(chuàng)建一個(gè)新的I/O完成端口。如果指定了有效的文件句柄(FileHandle)露久,則新創(chuàng)建的完成端口會(huì)和其關(guān)聯(lián)更米,否則只是新建一個(gè)完成端口。函數(shù)返回該新建的完成端口毫痕。

CompletionKey
包含于每個(gè)I/O完成封包中的用戶自定義的pre-handle征峦。

NumberOfConcurrentThreads
對(duì)每個(gè)I/O完成端口,操作系統(tǒng)允許的最大線程數(shù)以同時(shí)處理I/O完成封包消请。如果ExistingCompletionPort參數(shù)不為NULL栏笆,該參數(shù)會(huì)被忽略。
如果該參數(shù)為0臊泰,系統(tǒng)將允許和系統(tǒng)處理器個(gè)數(shù)一樣的線程數(shù)同時(shí)運(yùn)行蛉加。

Return value
函數(shù)執(zhí)行成功必然返回一個(gè)I/O完成端口。

  • 如果ExistingCompletionPortNULL缸逃,返回一個(gè)新的完成端口针饥。
  • 如果ExistingCompletionPort為一個(gè)有效的完成端口,則返回這個(gè)完成端口需频。
  • 如果FileHandle是一個(gè)有效的文件句柄丁眼,該文件句柄將會(huì)和返回的完成端口關(guān)聯(lián)。
  • 如果函數(shù)失敗贺辰,返回NULL户盯,可通過(guò)GetLastError函數(shù)獲取擴(kuò)展錯(cuò)誤碼嵌施。

Remarks
I/O完成端口和創(chuàng)建它的進(jìn)程關(guān)聯(lián),其它進(jìn)程不可見(jiàn)莽鸭,但是同一進(jìn)程內(nèi)的線程之間可共享吗伤。
文件句柄僅可和一個(gè)完成端口關(guān)聯(lián),一旦完成關(guān)聯(lián)硫眨,直到該文件句柄關(guān)閉該關(guān)聯(lián)將一直維持足淆。
可多次調(diào)用CreateIoCompletionPort函數(shù)將多個(gè)文件句柄關(guān)聯(lián)到一個(gè)完成端口上。
使用CompletionKey參數(shù)幫助應(yīng)用程序跟蹤究竟是哪個(gè)重疊IO已經(jīng)完成礁阁。這個(gè)參數(shù)并沒(méi)有參與CreateIoCompletionPort的內(nèi)部功能控制巧号,其只是綁定到文件句柄上。對(duì)于每個(gè)文件句柄來(lái)說(shuō)這個(gè)CompletionKey必須是唯一的姥闭,且其在整個(gè)內(nèi)部處理期間都會(huì)伴隨文件句柄丹鸿。當(dāng)完成封包到來(lái)時(shí),可通過(guò)GetQueuedCompletionStatus函數(shù)獲取這個(gè)CompletionKey棚品。CompletionKey也可用于PostQueuedCompletionStatus函數(shù)以入隊(duì)用戶自定義完成封包靠欢。

當(dāng)文件句柄和某IO完成端口關(guān)聯(lián)后,其不可再用于ReadFileEx函數(shù)和WriteFileEx函數(shù)铜跑,因?yàn)檫@些函數(shù)有它們自己的異步IO機(jī)制门怪。

最好不要以句柄繼承或調(diào)用DuplicateHandle函數(shù)的方式共享已經(jīng)與IO完成端口關(guān)聯(lián)的文件句柄。使用這種多重句柄執(zhí)行操作時(shí)也會(huì)產(chǎn)生完成通知锅纺,還是小心為妙掷空。

IO完成端口句柄和與其關(guān)聯(lián)的文件句柄我們稱之為IO完成端口引用(reference to the I/O completion port),當(dāng)沒(méi)有引用時(shí)必須釋放IO完成端口囤锉。所有這些句柄必須正確地關(guān)閉以釋放IO完成端口及其關(guān)聯(lián)的系統(tǒng)資源坦弟。當(dāng)滿足上述條件時(shí),可調(diào)用CloseHandle關(guān)閉IO完成端口嚼锄。

GetQueuedCompletionStatus

嘗試從指定的IO完成端口上出隊(duì)一個(gè)IO完成封包减拭。如果隊(duì)列中沒(méi)有完成封包,函數(shù)將等待完成端口上某個(gè)未決IO操作完成区丑。

如果需要一次出隊(duì)多個(gè)IO完成封包,使用GetQueuedCompletionStatusEx函數(shù)修陡。

Syntax

BOOL WINAPI GetQueuedCompletionStatus(
    _In_ HANDLE CompletionPort,
    _Out_ LPDWORD lpNumberOfBytes,
    _Out_ PULONG_PTR lpCompletionKey,
    _Out_ LPOVERLAPPED *lpOverlapped,
    _In_ DWORD dwMilliseconds
);

Parameters
CompletionPort
lpNumberOfBytes
用于保存已完成的IO操作在其執(zhí)行期間傳輸?shù)淖止?jié)總數(shù)沧侥。
lpCompletonKey
當(dāng)某文件句柄上的IO操作完成時(shí),用于保存與該文件句柄關(guān)聯(lián)的completion key的值魄鸦。
lpOverlapped
用于保存某OVERLAPPED結(jié)構(gòu)體的地址宴杀,其在IO操作開(kāi)始時(shí)被指定。

即使已將文件句柄和完成端口關(guān)聯(lián)且指定了有效的OVERLAPPED結(jié)構(gòu)拾因,應(yīng)用程序也可以阻止完成通知旺罢。為此旷余,必須在OVERLAPPED結(jié)構(gòu)的hEvent成員中保存一個(gè)有效的事件句柄并設(shè)置其最低位:

    Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    Overlapped.hEvent = (HANDLE) ((DWORD_PTR) Overlapped.hEvent | 1);
    ...

另外扁达,在關(guān)閉這個(gè)事件句柄時(shí)不要忘了將最低位清掉:

    CloseHandle((HANDLE) ((DWORD_PTR) Overlapped.hEvent & ~1));

dwMilliseconds
調(diào)用者愿意在完成端口上等待完成封包的毫秒數(shù)正卧。如果在指定的時(shí)間內(nèi)沒(méi)有完成封包出現(xiàn)跪解,函數(shù)將返回FALSE同時(shí)設(shè)置lpOverlappedNULL

如果為INFINITE惶看,函數(shù)將阻塞執(zhí)行莹桅。

Return value
這個(gè)函數(shù)將線程和指定的完成端口關(guān)聯(lián)煤禽。一個(gè)線程只能和一個(gè)完成端口關(guān)聯(lián)选脊。

當(dāng)調(diào)用GetQueuedCompletionStatus時(shí)如果與之關(guān)聯(lián)的完成端口已經(jīng)關(guān)閉钝的,函數(shù)將失敗并返回FALSE棍弄,且lpOverlappedNULL蛮原,同時(shí)GetLastError返回ERROR_ABANDONED_WAIT_0擴(kuò)展錯(cuò)誤碼蹦漠。

如果GetQueuedCompletionStatus函數(shù)執(zhí)行成功研铆,將從完成端口上出隊(duì)一個(gè)完成封包(對(duì)應(yīng)一個(gè)成功的IO操作)棵红,并將其信息存儲(chǔ)到lpNumberOfBytes, lpCompletionKeylpOverlapped參數(shù)中;如果執(zhí)行失敗咧栗,這些參數(shù)可能包含以下特定的值:

  • 如果lpOverlappedNULL逆甜,函數(shù)沒(méi)有從完成端口上出隊(duì)一個(gè)完成封包,這種情況下致板,函數(shù)不會(huì)在lpNumberOfBytes, lpCompletionKey中存儲(chǔ)信息忆绰,它們的值是不確定的。
  • 如果lpOverlapped不為NULL可岂,函數(shù)從完成端口上出隊(duì)一個(gè)完成封包,但該完成封包對(duì)應(yīng)一個(gè)失敗的IO操作翰灾,函數(shù)會(huì)將該失敗的IO操作的信息存儲(chǔ)到lpNumberOfBytes, lpCompletionKeylpOverlapped中缕粹,可通過(guò)GetLastError獲取擴(kuò)展錯(cuò)誤碼稚茅。

PostQueuedCompletionStatus

向完成端口提交一個(gè)IO完成封包。

Syntax

BOOL WINAPI PostQueuedCompletionStatus(
    _In_ HANDLE CompletionPort,
    _In_ DWORD dwNubmerOfBytesTransferred,
    _In_ ULONG_PTR dwCompletionKey,
    _In_opt_ LPOVERLAPPED lpOverlapped
);

Parameters
CompletionPort

dwNumberOfBytesTransferred
dwCompletonKey
lpOverlapped
上述3個(gè)參數(shù)指定當(dāng)調(diào)用GetQueuedCompletionStatus時(shí)對(duì)應(yīng)參數(shù)帶回的值平斩。

Return value
函數(shù)執(zhí)行成功返回非零值亚享,否則返回0.

Remarks
提交的完成封包完全滿足GetQueuedCompletonStatus的要求。系統(tǒng)不會(huì)使用這個(gè)封包也不會(huì)驗(yàn)證其正確性绘面。尤其是欺税,lpOverlapped參數(shù)不必是指向OVERLAPPED結(jié)構(gòu)體的指針。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末揭璃,一起剝皮案震驚了整個(gè)濱河市触趴,隨后出現(xiàn)的幾起案子载碌,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件眯娱,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡沙峻,警方通過(guò)查閱死者的電腦和手機(jī)益涧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)院崇,“玉大人肆氓,你說(shuō)我怎么就攤上這事〉装辏” “怎么了谢揪?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)濒持。 經(jīng)常有香客問(wèn)我键耕,道長(zhǎng),這世上最難降的妖魔是什么柑营? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任屈雄,我火速辦了婚禮,結(jié)果婚禮上官套,老公的妹妹穿的比我還像新娘酒奶。我一直安慰自己,他們只是感情好奶赔,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布惋嚎。 她就那樣靜靜地躺著,像睡著了一般站刑。 火紅的嫁衣襯著肌膚如雪另伍。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 50,096評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音摆尝,去河邊找鬼温艇。 笑死,一個(gè)胖子當(dāng)著我的面吹牛堕汞,可吹牛的內(nèi)容都是我干的勺爱。 我是一名探鬼主播,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼讯检,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼琐鲁!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起人灼,我...
    開(kāi)封第一講書(shū)人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤围段,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后挡毅,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蒜撮,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年跪呈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了段磨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡耗绿,死狀恐怖苹支,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情误阻,我是刑警寧澤债蜜,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布,位于F島的核電站究反,受9級(jí)特大地震影響寻定,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜精耐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一狼速、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧卦停,春花似錦向胡、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至小槐,卻和暖如春拇派,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工攀痊, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留桐腌,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓苟径,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親躬审。 傳聞我的和親對(duì)象是個(gè)殘疾皇子棘街,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

  • 非原創(chuàng)文章,網(wǎng)絡(luò)收集承边,如遇原作者遭殉,請(qǐng)私聊會(huì)標(biāo)明出處! 1--11 tcp協(xié)議中三次握手和四次揮手建立TCP需要三次...
    Juinjonn閱讀 2,159評(píng)論 0 28
  • ORA-00001: 違反唯一約束條件 (.) 錯(cuò)誤說(shuō)明:當(dāng)在唯一索引所對(duì)應(yīng)的列上鍵入重復(fù)值時(shí)博助,會(huì)觸發(fā)此異常险污。 O...
    我想起個(gè)好名字閱讀 5,259評(píng)論 0 9
  • 前言:在之前的面試中窖式,每每問(wèn)到關(guān)于Java I/O 方面的東西都感覺(jué)自己吃了大虧..所以這里搶救一下..來(lái)深入的了...
    我沒(méi)有三顆心臟閱讀 2,488評(píng)論 0 21
  • 一蚁飒、溫故而知新 1. 內(nèi)存不夠怎么辦 內(nèi)存簡(jiǎn)單分配策略的問(wèn)題地址空間不隔離內(nèi)存使用效率低程序運(yùn)行的地址不確定 關(guān)于...
    SeanCST閱讀 7,787評(píng)論 0 27
  • 記得高考前語(yǔ)文作文訓(xùn)練時(shí),劉老師強(qiáng)調(diào)題目不能太抽象萝喘。今天下筆寫文時(shí)淮逻,還是找了這么土里土氣的題目,來(lái)紀(jì)念那段青...
    西樓聽(tīng)雨客閱讀 422評(píng)論 0 1