锘??xml version="1.0" encoding="utf-8" standalone="yes"?>
1銆佸熀鏈蹇?br>2銆乄INDOWS瀹屾垚绔彛鐨勭壒鐐?br>3銆佸畬鎴愮鍙o紙Completion Ports 錛夌浉鍏蟲暟鎹粨鏋勫拰鍒涘緩
4銆佸畬鎴愮鍙g嚎紼嬬殑宸ヤ綔鍘熺悊
5銆乄indows瀹屾垚绔彛鐨勫疄渚嬩唬鐮?br>Linux鐨凟Poll妯″瀷
1銆佷負浠涔坰elect钀藉悗
2銆佸唴鏍鎬腑鎻愰珮I(yè)/O鎬ц兘鐨勬柊鏂規(guī)硶epoll
3銆乪poll鐨勪紭鐐?br>4銆乪poll鐨勫伐浣滄ā寮?
5銆乪poll鐨勪嬌鐢ㄦ柟娉?br>6銆丩inux涓婨POll緙栫▼瀹炰緥
鎬葷粨
WINDOWS瀹屾垚绔彛緙栫▼
鎽樿錛氬紑鍙戠綉緇滅▼搴忎粠鏉ラ兘涓嶆槸涓浠跺鏄撶殑浜嬫儏錛屽敖綆″彧闇瑕侀伒瀹堝緢灝戠殑涓浜涜鍒?鍒涘緩socket,鍙戣搗榪炴帴錛屾帴鍙楄繛鎺ワ紝鍙戦佸拰鎺ュ彈鏁版嵁銆傜湡姝g殑鍥伴毦鍦ㄤ簬錛?
璁╀綘鐨勭▼搴忓彲浠ラ傚簲浠庡崟鍗曚竴涓繛鎺ュ埌鍑犲崈涓繛鎺ヤ箖鑷充簬涓婁竾涓繛鎺ャ傚埄鐢╓indows騫沖彴瀹屾垚绔彛榪涜閲嶅彔I/O鐨勬妧鏈拰Linux鍦?.6鐗堟湰鐨勫唴鏍鎬腑
寮曞叆鐨凟POll鎶鏈紝鍙互寰堟柟渚垮湪鍦ㄥ湪Windows鍜孡inux騫沖彴涓婂紑鍙戝嚭鏀寔澶ч噺榪炴帴鐨勭綉緇滄湇鍔$▼搴忋傛湰鏂囦粙緇嶅湪Windows鍜孡inux騫沖彴
涓婁嬌鐢ㄧ殑瀹屾垚绔彛鍜孍Poll妯″瀷寮鍙戠殑鍩烘湰鍘熺悊錛屽悓鏃剁粰鍑哄疄闄呯殑渚嬪瓙銆傛湰鏂囦富瑕佸叧娉–/S緇撴瀯鐨勬湇鍔″櫒绔▼搴忥紝鍥犱負涓鑸潵璇達紝寮鍙戜竴涓ぇ瀹歸噺錛屽叿鍙墿灞?
鎬х殑winsock紼嬪簭涓鑸氨鏄寚鏈嶅姟紼嬪簭銆?br>
1銆佸熀鏈蹇?br>
璁懼---windows鎿嶄綔緋葷粺涓婂厑璁擱氫俊鐨勪換浣曚笢瑗匡紝姣斿鏂囦歡銆佺洰褰曘佷覆琛屽彛銆佸茍琛屽彛銆侀偖浠舵Ы銆佸懡鍚嶇閬撱佹棤鍚嶇閬撱佸鎺ュ瓧銆佹帶鍒跺彴銆侀昏緫紓佺洏銆佺墿鐞?
紓佺洏絳夈傜粷澶у鏁頒笌璁懼鎵撲氦閬撶殑鍑芥暟閮芥槸CreateFile/ReadFile/WriteFile絳夈傛墍浠ユ垜浠笉鑳界湅鍒?*File鍑芥暟灝卞彧鎯沖埌鏂囦歡
璁懼銆備笌璁懼閫氫俊鏈変袱縐嶆柟寮忥紝鍚屾鏂瑰紡鍜屽紓姝ユ柟寮忋傚悓姝ユ柟寮忎笅錛屽綋璋冪敤ReadFile鍑芥暟鏃訛紝鍑芥暟浼氱瓑寰呯郴緇熸墽琛屽畬鎵瑕佹眰鐨勫伐浣滐紝鐒跺悗鎵嶈繑鍥烇紱寮傛鏂瑰紡
涓嬶紝ReadFile榪欑被鍑芥暟浼氱洿鎺ヨ繑鍥烇紝緋葷粺鑷繁鍘誨畬鎴愬璁懼鐨勬搷浣滐紝鐒跺悗浠ユ煇縐嶆柟寮忛氱煡瀹屾垚鎿嶄綔銆?br>閲嶅彔I/O----欏懼悕鎬濅箟錛屽綋浣犺皟鐢ㄤ簡鏌?
涓嚱鏁幫紙姣斿ReadFile錛夊氨绔嬪埢榪斿洖鍋氳嚜宸辯殑鍏朵粬鍔ㄤ綔鐨勬椂鍊欙紝鍚屾椂緋葷粺涔熷湪瀵笽/0璁懼榪涜浣犺姹傜殑鎿嶄綔錛屽湪榪欐鏃墮棿鍐呬綘鐨勭▼搴忓拰緋葷粺鐨勫唴閮ㄥ姩浣滄槸
閲嶅彔鐨勶紝鍥犳鏈夋洿濂界殑鎬ц兘銆傛墍浠ワ紝閲嶅彔I/O鏄敤浜庡紓姝ユ柟寮忎笅浣跨敤I/O璁懼鐨勩?閲嶅彔I/O闇瑕佷嬌鐢ㄧ殑涓涓潪甯擱噸瑕佺殑鏁版嵁緇撴瀯OVERLAPPED銆?br>
2銆乄INDOWS瀹屾垚绔彛鐨勭壒鐐?br>
Win32閲嶅彔I/O(Overlapped
I/O)鏈哄埗鍏佽鍙戣搗涓涓搷浣滐紝鐒跺悗鍦ㄦ搷浣滃畬鎴愪箣鍚庢帴鍙楀埌淇℃伅銆傚浜庨偅縐嶉渶瑕佸緢闀挎椂闂存墠鑳藉畬鎴愮殑鎿嶄綔鏉ヨ錛岄噸鍙營O鏈哄埗灝ゅ叾鏈夌敤錛屽洜涓哄彂璧烽噸鍙犳搷浣滅殑綰跨▼
鍦ㄩ噸鍙犺姹傚彂鍑哄悗灝卞彲浠ヨ嚜鐢辯殑鍋氬埆鐨勪簨鎯呬簡銆傚湪WinNT鍜學in2000涓婏紝鎻愪緵鐨勭湡姝g殑鍙墿灞曠殑I/O妯″瀷灝辨槸浣跨敤瀹屾垚绔彛錛圕ompletion
Port錛夌殑閲嶅彔I/O.瀹屾垚绔彛---鏄竴縐峎INDOWS鍐呮牳瀵硅薄銆傚畬鎴愮鍙g敤浜庡紓姝ユ柟寮忕殑閲嶅彔I/0鎯呭喌涓嬶紝褰撶劧閲嶅彔I/O涓嶄竴瀹氶潪浣跨敤瀹屾垚绔彛涓?
鍙紝榪樻湁璁懼鍐呮牳瀵硅薄銆佷簨浠跺璞°佸憡璀/0絳夈備絾鏄畬鎴愮鍙e唴閮ㄦ彁渚涗簡綰跨▼姹犵殑綆$悊錛屽彲浠ラ伩鍏嶅弽澶嶅垱寤虹嚎紼嬬殑寮閿錛屽悓鏃跺彲浠ユ牴鎹瓹PU鐨勪釜鏁扮伒媧葷殑鍐沖畾
綰跨▼涓暟錛岃屼笖鍙互璁╁噺灝戠嚎紼嬭皟搴︾殑嬈℃暟浠庤屾彁楂樻ц兘鍏跺疄綾諱技浜嶹SAAsyncSelect鍜宻elect鍑芥暟鐨勬満鍒舵洿瀹規(guī)槗鍏煎Unix錛屼絾鏄毦浠ュ疄鐜?
鎴戜滑鎯寵鐨?#8220;鎵╁睍鎬?#8221;銆傝屼笖windows鐨勫畬鎴愮鍙f満鍒跺湪鎿嶄綔緋葷粺鍐呴儴宸茬粡浣滀簡浼樺寲錛屾彁渚涗簡鏇撮珮鐨勬晥鐜囥傛墍浠ワ紝鎴戜滑閫夋嫨瀹屾垚绔彛寮濮嬫垜浠殑鏈嶅姟鍣ㄧ▼搴忕殑
寮鍙戙?br>1銆佸彂璧鋒搷浣滀笉涓瀹氬畬鎴愶紝緋葷粺浼氬湪瀹屾垚鐨勬椂鍊欓氱煡浣狅紝閫氳繃鐢ㄦ埛鍦ㄥ畬鎴愮鍙d笂鐨勭瓑寰咃紝澶勭悊鎿嶄綔鐨勭粨鏋溿傛墍浠ヨ鏈夋鏌ュ畬鎴愮鍙o紝鍙栨搷浣滅粨鏋滅殑綰?
紼嬨傚湪瀹屾垚绔彛涓婂畧鍊欑殑綰跨▼緋葷粺鏈変紭鍖栵紝闄ら潪鍦ㄦ墽琛岀殑綰跨▼闃誨錛屼笉浼氭湁鏂扮殑綰跨▼琚縺媧伙紝浠ユ鏉ュ噺灝戠嚎紼嬪垏鎹㈤犳垚鐨勬ц兘浠d環(huán)銆傛墍浠ュ鏋滅▼搴忎腑娌℃湁澶鐨勯樆濉?
鎿嶄綔錛屾病鏈夊繀瑕佸惎鍔ㄥお澶氱殑綰跨▼錛孋PU鏁伴噺鐨勪袱鍊嶏紝涓鑸繖鏍鋒潵鍚姩綰跨▼銆?br>2銆佹搷浣滀笌鐩稿叧鏁版嵁鐨勭粦瀹氭柟寮忥細鍦ㄦ彁浜ゆ暟鎹殑鏃跺欑敤鎴峰鏁版嵁鎵撶浉搴旂殑鏍囪錛岃褰曟搷浣滅殑綾誨瀷錛屽湪鐢ㄦ埛澶勭悊鎿嶄綔緇撴灉鐨勬椂鍊欙紝閫氳繃媯鏌ヨ嚜宸辨墦鐨勬爣璁板拰緋葷粺鐨勬搷浣滅粨鏋滆繘琛岀浉搴旂殑澶勭悊銆?
3銆?
鎿嶄綔榪斿洖鐨勬柟寮?涓鑸搷浣滃畬鎴愬悗瑕侀氱煡紼嬪簭榪涜鍚庣畫澶勭悊銆備絾鍐欐搷浣滃彲浠ヤ笉閫氱煡鐢ㄦ埛錛屾鏃跺鏋滅敤鎴峰啓鎿嶄綔涓嶈兘椹笂瀹屾垚錛屽啓鎿嶄綔鐨勭浉鍏蟲暟鎹細琚殏瀛樺埌鍒伴潪浜ゆ崲
緙撳啿鍖轟腑錛屽湪鎿嶄綔瀹屾垚鐨勬椂鍊欙紝緋葷粺浼氳嚜鍔ㄩ噴鏀劇紦鍐插尯銆傛鏃跺彂璧峰畬鍐欐搷浣滐紝浣跨敤鐨勫唴瀛樺氨鍙互閲婃斁浜嗐傛鏃跺鏋滃崰鐢ㄩ潪浜ゆ崲緙撳啿澶浼氫嬌緋葷粺鍋滄鍝嶅簲銆?br>
3銆佸畬鎴愮鍙o紙Completion Ports 錛夌浉鍏蟲暟鎹粨鏋勫拰鍒涘緩
鍏跺疄鍙互鎶婂畬鎴愮鍙g湅鎴愮郴緇熺淮鎶ょ殑涓涓槦鍒楋紝鎿嶄綔緋葷粺鎶婇噸鍙營O鎿嶄綔瀹屾垚鐨勪簨浠墮氱煡鏀懼埌璇ラ槦鍒楅噷錛岀敱浜庢槸鏆撮湶
“鎿嶄綔瀹屾垚”鐨勪簨浠墮氱煡錛屾墍浠ュ懡鍚嶄負“瀹屾垚绔彛”錛圕Ompletion
Ports錛夈備竴涓猻ocket琚垱寤哄悗錛屽彲浠ュ湪浠諱綍鏃跺埢鍜屼竴涓畬鎴愮鍙h仈緋昏搗鏉ャ?br>瀹屾垚绔彛鐩稿叧鏈閲嶈鐨勬槸OVERLAPPED鏁版嵁緇撴瀯
typedef struct _OVERLAPPED {
ULONG_PTR Internal;//琚郴緇熷唴閮ㄨ祴鍊鹼紝鐢ㄦ潵琛ㄧず緋葷粺鐘舵?
ULONG_PTR InternalHigh;// 琚郴緇熷唴閮ㄨ祴鍊鹼紝浼犺緭鐨勫瓧鑺傛暟
union {
struct {
DWORD Offset;//鍜孫ffsetHigh鍚堟垚涓涓?4浣嶇殑鏁存暟錛岀敤鏉ヨ〃紺轟粠鏂囦歡澶撮儴鐨勫灝戝瓧鑺傚紑濮?
DWORD OffsetHigh;//鎿嶄綔錛屽鏋滀笉鏄鏂囦歡I/O鏉ユ搷浣滐紝鍒欏繀欏昏瀹氫負0
};
PVOID Pointer;
};
HANDLE hEvent;//濡傛灉涓嶄嬌鐢紝灝卞姟蹇呰涓?,鍚﹀垯璇瘋祴涓涓湁鏁堢殑Event鍙ユ焺
} OVERLAPPED, *LPOVERLAPPED;
涓嬮潰鏄紓姝ユ柟寮忎嬌鐢≧eadFile鐨勪竴涓緥瀛?
OVERLAPPED Overlapped;
Overlapped.Offset=345;
Overlapped.OffsetHigh=0;
Overlapped.hEvent=0;
//鍋囧畾鍏朵粬鍙傛暟閮藉凡緇忚鍒濆鍖?
ReadFile(hFile,buffer,sizeof(buffer),&dwNumBytesRead,&Overlapped);
榪欐牱灝卞畬鎴愪簡寮傛鏂瑰紡璇繪枃浠剁殑鎿嶄綔錛岀劧鍚嶳eadFile鍑芥暟榪斿洖錛岀敱鎿嶄綔緋葷粺鍋氳嚜宸辯殑浜嬫儏錛屼笅闈粙緇嶅嚑涓笌OVERLAPPED緇撴瀯鐩稿叧鐨勫嚱鏁?
絳夊緟閲嶅彔I/0鎿嶄綔瀹屾垚鐨勫嚱鏁?
BOOL GetOverlappedResult (
HANDLE hFile,
LPOVERLAPPED lpOverlapped,//鎺ュ彈榪斿洖鐨勯噸鍙營/0緇撴瀯
LPDWORD lpcbTransfer,//鎴愬姛浼犺緭浜嗗灝戝瓧鑺傛暟
BOOL fWait //TRUE鍙湁褰撴搷浣滃畬鎴愭墠榪斿洖錛孎ALSE鐩存帴榪斿洖錛屽鏋滄搷浣滄病鏈夊畬鎴愶紝閫氳繃璋?/鐢℅etLastError ( )鍑芥暟浼氳繑鍥濫RROR_IO_INCOMPLETE
);
瀹廐asOverlappedIoCompleted鍙互甯姪鎴戜滑嫻嬭瘯閲嶅彔I/0鎿嶄綔鏄惁瀹屾垚錛岃瀹忓OVERLAPPED緇撴瀯鐨処nternal鎴愬憳榪涜浜嗘祴璇曪紝鏌ョ湅鏄惁絳変簬STATUS_PENDING鍊箋?/p>
涓鑸潵璇達紝涓涓簲鐢ㄧ▼搴忓彲浠ュ垱寤哄涓伐浣滅嚎紼嬫潵澶勭悊瀹屾垚绔彛涓婄殑閫氱煡浜嬩歡銆傚伐浣滅嚎紼嬬殑鏁伴噺渚濊禆浜庣▼搴忕殑鍏蜂綋闇瑕併備絾鏄湪鐞嗘兂鐨勬儏鍐典笅錛屽簲璇ュ搴斾竴涓狢PU
鍒涘緩涓涓嚎紼嬨傚洜涓哄湪瀹屾垚绔彛鐞嗘兂妯″瀷涓紝姣忎釜綰跨▼閮藉彲浠ヤ粠緋葷粺鑾峰緱涓涓?#8220;鍘熷瓙”鎬х殑鏃墮棿鐗囷紝杞暘榪愯騫舵鏌ュ畬鎴愮鍙o紝綰跨▼鐨勫垏鎹㈡槸棰濆鐨勫紑閿銆傚湪瀹為檯寮
鍙戠殑鏃跺欙紝榪樿鑰冭檻榪欎簺綰跨▼鏄惁鐗墊秹鍒板叾浠栧牭濉炴搷浣滅殑鎯呭喌銆傚鏋滄煇綰跨▼榪涜鍫靛鎿嶄綔錛岀郴緇熷垯灝嗗叾鎸傝搗錛岃鍒殑綰跨▼鑾峰緱榪愯鏃墮棿銆傚洜姝わ紝濡傛灉鏈夎繖鏍風殑鎯呭喌錛?
鍙互澶氬垱寤哄嚑涓嚎紼嬫潵灝介噺鍒╃敤鏃墮棿銆?br>搴旂敤瀹屾垚绔彛錛?br> 鍒涘緩瀹屾垚绔彛錛氬畬鎴愮鍙f槸涓涓唴鏍稿璞★紝浣跨敤鏃朵粬鎬繪槸瑕佸拰鑷沖皯涓涓湁鏁堢殑璁懼鍙ユ焺榪涜鍏寵仈錛屽畬鎴愮鍙f槸涓涓鏉傜殑鍐呮牳瀵硅薄錛屽垱寤哄畠鐨勫嚱鏁版槸錛?br>HANDLE CreateIoCompletionPort(
IN HANDLE FileHandle,
IN HANDLE ExistingCompletionPort,
IN ULONG_PTR CompletionKey,
IN DWORD NumberOfConcurrentThreads
);
閫氬父鍒涘緩宸ヤ綔鍒嗕袱姝ワ細
絎竴姝ワ紝鍒涘緩涓涓柊鐨勫畬鎴愮鍙e唴鏍稿璞★紝鍙互浣跨敤涓嬮潰鐨勫嚱鏁幫細
HANDLE CreateNewCompletionPort(DWORD dwNumberOfThreads)
{
return CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,NULL,dwNumberOfThreads);
};
絎簩姝ワ紝灝嗗垰鍒涘緩鐨勫畬鎴愮鍙e拰涓涓湁鏁堢殑璁懼鍙ユ焺鍏寵仈璧鋒潵錛屽彲浠ヤ嬌鐢ㄤ笅闈㈢殑鍑芥暟錛?br> bool AssicoateDeviceWithCompletionPort(HANDLE hCompPort,HANDLE hDevice,DWORD dwCompKey)
{
HANDLE h=CreateIoCompletionPort(hDevice,hCompPort,dwCompKey,0);
return h==hCompPort;
};
璇存槑
1錛?CreateIoCompletionPort鍑芥暟涔熷彲浠ヤ竴嬈℃х殑鏃㈠垱寤哄畬鎴愮鍙e璞★紝鍙堝叧鑱斿埌涓涓湁鏁堢殑璁懼鍙ユ焺
2錛?CompletionKey鏄竴涓彲浠ヨ嚜宸卞畾涔夌殑鍙傛暟錛屾垜浠彲浠ユ妸涓涓粨鏋勭殑鍦板潃璧嬬粰瀹冿紝鐒跺悗鍦ㄥ悎閫傜殑鏃跺欏彇鍑烘潵浣跨敤錛屾渶濂借淇濊瘉緇撴瀯閲岄潰鐨勫唴瀛樹笉鏄垎閰嶅湪鏍堜笂錛岄櫎闈炰綘鏈夊崄鍒嗙殑鎶婃彙鍐呭瓨浼氫繚鐣欏埌浣犺浣跨敤鐨勯偅涓鍒匯?br>3錛?
NumberOfConcurrentThreads閫氬父鐢ㄦ潵鎸囧畾瑕佸厑璁稿悓鏃惰繍琛岀殑鐨勭嚎紼嬬殑鏈澶т釜鏁般傞氬父鎴戜滑鎸囧畾涓?錛岃繖鏍風郴緇熶細鏍規(guī)嵁CPU鐨勪釜鏁版潵鑷?
鍔ㄧ‘瀹氥傚垱寤哄拰鍏寵仈鐨勫姩浣滃畬鎴愬悗錛岀郴緇熶細灝嗗畬鎴愮鍙e叧鑱旂殑璁懼鍙ユ焺銆佸畬鎴愰敭浣滀負涓鏉$邯褰曞姞鍏ュ埌榪欎釜瀹屾垚绔彛鐨勮澶囧垪琛ㄤ腑銆傚鏋滀綘鏈夊涓畬鎴愮鍙o紝灝變細鏈夊
涓搴旂殑璁懼鍒楄〃銆傚鏋滆澶囧彞鏌勮鍏抽棴錛屽垯琛ㄤ腑鑷姩鍒犻櫎璇ョ邯褰曘?br>
4銆佸畬鎴愮鍙g嚎紼嬬殑宸ヤ綔鍘熺悊
瀹屾垚绔彛鍙互甯姪鎴戜滑綆$悊綰跨▼姹狅紝浣嗘槸綰跨▼姹犱腑鐨勭嚎紼嬮渶瑕佹垜浠嬌鐢╛beginthreadex鏉ュ垱寤猴紝鍑粈涔堥氱煡瀹屾垚绔彛綆$悊鎴戜滑鐨勬柊綰跨▼鍛紵絳旀鍦ㄥ嚱鏁癎etQueuedCompletionStatus銆傝鍑芥暟鍘熷瀷錛?
BOOL GetQueuedCompletionStatus(
IN HANDLE CompletionPort,
OUT LPDWORD lpNumberOfBytesTransferred,
OUT PULONG_PTR lpCompletionKey,
OUT LPOVERLAPPED *lpOverlapped,
IN DWORD dwMilliseconds
);
榪?
涓嚱鏁拌瘯鍥句粠鎸囧畾鐨勫畬鎴愮鍙g殑I/0瀹屾垚闃熷垪涓娊鍙栫邯褰曘傚彧鏈夊綋閲嶅彔I/O鍔ㄤ綔瀹屾垚鐨勬椂鍊欙紝瀹屾垚闃熷垪涓墠鏈夌邯褰曘傚嚒鏄皟鐢ㄨ繖涓嚱鏁扮殑綰跨▼灝嗚鏀懼叆鍒板畬鎴愮
鍙g殑絳夊緟綰跨▼闃熷垪涓紝鍥犳瀹屾垚绔彛灝卞彲浠ュ湪鑷繁鐨勭嚎紼嬫睜涓府鍔╂垜浠淮鎶よ繖涓嚎紼嬨傚畬鎴愮鍙g殑I/0瀹屾垚闃熷垪涓瓨鏀句簡褰撻噸鍙營/0瀹屾垚鐨勭粨鏋?---
涓鏉$邯褰曪紝璇ョ邯褰曟嫢鏈夊洓涓瓧孌碉紝鍓嶄笁欏瑰氨瀵瑰簲GetQueuedCompletionStatus鍑芥暟鐨?銆?銆?鍙傛暟錛屾渶鍚庝竴涓瓧孌墊槸閿欒淇℃伅
dwError銆傛垜浠篃鍙互閫氳繃璋冪敤PostQueudCompletionStatus妯℃嫙瀹屾垚浜嗕竴涓噸鍙營/0鎿嶄綔銆?
褰揑/0瀹屾垚闃熷垪涓?
鍑虹幇浜嗙邯褰曪紝瀹屾垚绔彛灝嗕細媯鏌ョ瓑寰呯嚎紼嬮槦鍒楋紝璇ラ槦鍒椾腑鐨勭嚎紼嬮兘鏄氳繃璋冪敤GetQueuedCompletionStatus鍑芥暟浣胯嚜宸卞姞鍏ラ槦鍒楃殑銆傜瓑寰?
綰跨▼闃熷垪寰堢畝鍗曪紝鍙槸淇濆瓨浜嗚繖浜涚嚎紼嬬殑ID銆傚畬鎴愮鍙d細鎸夌収鍚庤繘鍏堝嚭鐨勫師鍒欏皢涓涓嚎紼嬮槦鍒楃殑ID鏀懼叆鍒伴噴鏀劇嚎紼嬪垪琛ㄤ腑錛屽悓鏃惰綰跨▼灝嗕粠絳夊緟
GetQueuedCompletionStatus鍑芥暟榪斿洖鐨勭潯鐪犵姸鎬佷腑鍙樹負鍙皟搴︾姸鎬佺瓑寰匔PU鐨勮皟搴︺傛墍浠ユ垜浠殑綰跨▼瑕佹兂鎴愪負瀹屾垚绔彛綆$悊鐨勭嚎紼嬶紝
灝卞繀欏昏璋冪敤GetQueuedCompletionStatus鍑芥暟銆傚嚭浜庢ц兘鐨勪紭鍖栵紝瀹為檯涓婂畬鎴愮鍙h繕緇存姢浜嗕竴涓殏鍋滅嚎紼嬪垪琛紝鍏蜂綋緇嗚妭鍙互鍙傝?
銆奧indows楂樼駭緙栫▼鎸囧崡銆嬶紝鎴戜滑鐜板湪鐭ラ亾鐨勭煡璇嗭紝宸茬粡瓚沖浜嗐?
瀹屾垚绔彛綰跨▼闂存暟鎹紶閫掔嚎紼嬮棿浼犻掓暟鎹渶甯哥敤鐨勫姙娉曟槸鍦╛beginthreadex鍑芥暟涓皢鍙傛暟浼犻掔粰綰跨▼鍑芥暟錛屾垨鑰呬嬌鐢ㄥ叏灞鍙橀噺銆備絾鏄畬鎴愮鍙h繕鏈夎嚜
宸辯殑浼犻掓暟鎹殑鏂規(guī)硶錛岀瓟妗堝氨鍦ㄤ簬CompletionKey鍜孫VERLAPPED鍙傛暟銆?br>CompletionKey琚繚瀛樺湪瀹屾垚绔彛鐨勮澶囪〃
涓紝鏄拰璁懼鍙ユ焺涓涓瀵瑰簲鐨勶紝鎴戜滑鍙互灝嗕笌璁懼鍙ユ焺鐩稿叧鐨勬暟鎹繚瀛樺埌CompletionKey涓紝鎴栬呭皢CompletionKey琛ㄧず涓虹粨鏋勬寚閽堬紝榪?
鏍峰氨鍙互浼犻掓洿鍔犱赴瀵岀殑鍐呭銆傝繖浜涘唴瀹瑰彧鑳藉湪涓寮濮嬪叧鑱斿畬鎴愮鍙e拰璁懼鍙ユ焺鐨勬椂鍊欏仛錛屽洜姝や笉鑳藉湪浠ュ悗鍔ㄦ佹敼鍙樸?br>OVERLAPPED鍙傛暟鏄湪姣忔
璋冪敤ReadFile榪欐牱鐨勬敮鎸侀噸鍙營/0鐨勫嚱鏁版椂浼犻掔粰瀹屾垚绔彛鐨勩傛垜浠彲浠ョ湅鍒幫紝濡傛灉鎴戜滑涓嶆槸瀵規(guī)枃浠惰澶囧仛鎿嶄綔錛岃緇撴瀯鐨勬垚鍛樺彉閲忓氨瀵規(guī)垜浠嚑涔庢鏃犱綔
鐢ㄣ傛垜浠渶瑕侀檮鍔犱俊鎭紝鍙互鍒涘緩鑷繁鐨勭粨鏋勶紝鐒跺悗灝哋VERLAPPED緇撴瀯鍙橀噺浣滀負鎴戜滑緇撴瀯鍙橀噺鐨勭涓涓垚鍛橈紝鐒跺悗浼犻掔涓涓垚鍛樺彉閲忕殑鍦板潃緇?
ReadFile鍑芥暟銆傚洜涓虹被鍨嬪尮閰嶏紝褰撶劧鍙互閫氳繃緙栬瘧銆傚綋GetQueuedCompletionStatus鍑芥暟榪斿洖鏃訛紝鎴戜滑鍙互鑾峰彇鍒扮涓涓垚鍛樺彉
閲忕殑鍦板潃錛岀劧鍚庝竴涓畝鍗曠殑寮哄埗杞崲錛屾垜浠氨鍙互鎶婂畠褰撲綔瀹屾暣鐨勮嚜瀹氫箟緇撴瀯鐨勬寚閽堜嬌鐢紝榪欐牱灝卞彲浠ヤ紶閫掑緢澶氶檮鍔犵殑鏁版嵁浜嗐傚お濂戒簡錛佸彧鏈変竴鐐硅娉ㄦ剰錛屽鏋滆法綰?
紼嬩紶閫掞紝璇鋒敞鎰忓皢鏁版嵁鍒嗛厤鍒板爢涓婏紝騫朵笖鎺ユ敹绔簲璇ュ皢鏁版嵁鐢ㄥ畬鍚庨噴鏀俱傛垜浠氬父闇瑕佸皢ReadFile榪欐牱鐨勫紓姝ュ嚱鏁扮殑鎵闇瑕佺殑緙撳啿鍖烘斁鍒版垜浠嚜瀹氫箟鐨勭粨鏋?
涓紝榪欐牱褰揋etQueuedCompletionStatus琚繑鍥炴椂錛屾垜浠殑鑷畾涔夌粨鏋勭殑緙撳啿鍖哄彉閲忎腑灝卞瓨鏀句簡I/0鎿嶄綔鐨勬暟鎹?
CompletionKey鍜孫VERLAPPED鍙傛暟錛岄兘鍙互閫氳繃GetQueuedCompletionStatus鍑芥暟鑾峰緱銆?br>綰跨▼鐨勫畨鍏ㄩ鍑?br> 寰堝綰跨▼涓轟簡涓嶆涓嬈$殑鎵ц寮傛鏁版嵁澶勭悊錛岄渶瑕佷嬌鐢ㄥ涓嬭鍙?br>while (true)
{
......
GetQueuedCompletionStatus(...);
......
}
閭d箞濡備綍閫鍑哄憿錛岀瓟妗堝氨鍦ㄤ簬涓婇潰鏇炬彁鍒扮殑PostQueudCompletionStatus鍑芥暟錛屾垜浠彲浠ョ敤瀹冨彂閫佷竴涓嚜瀹氫箟鐨勫寘鍚簡OVERLAPPED鎴愬憳鍙橀噺鐨勭粨鏋勫湴鍧錛岄噷闈㈠寘鍚竴涓姸鎬佸彉閲忥紝褰撶姸鎬佸彉閲忎負閫鍑烘爣蹇楁椂錛岀嚎紼嬪氨鎵ц娓呴櫎鍔ㄤ綔鐒跺悗閫鍑恒?br>
5銆乄indows瀹屾垚绔彛鐨勫疄渚嬩唬鐮侊細
DWORD WINAPI WorkerThread(LPVOID lpParam)
{
ULONG_PTR *PerHandleKey;
OVERLAPPED *Overlap;
OVERLAPPEDPLUS *OverlapPlus,
*newolp;
DWORD dwBytesXfered;
while (1)
{
ret = GetQueuedCompletionStatus(
hIocp,
&dwBytesXfered,
(PULONG_PTR)&PerHandleKey,
&Overlap,
INFINITE);
if (ret == 0)
{
// Operation failed
continue;
}
OverlapPlus = CONTAINING_RECORD(Overlap, OVERLAPPEDPLUS, ol);
switch (OverlapPlus->OpCode)
{
case OP_ACCEPT:
// Client socket is contained in OverlapPlus.sclient
// Add client to completion port
CreateIoCompletionPort(
(HANDLE)OverlapPlus->sclient,
hIocp,
(ULONG_PTR)0,
0);
// Need a new OVERLAPPEDPLUS structure
// for the newly accepted socket. Perhaps
// keep a look aside list of free structures.
newolp = AllocateOverlappedPlus();
if (!newolp)
{
// Error
}
newolp->s = OverlapPlus->sclient;
newolp->OpCode = OP_READ;
// This function divpares the data to be sent
PrepareSendBuffer(&newolp->wbuf);
ret = WSASend(
newolp->s,
&newolp->wbuf,
1,
&newolp->dwBytes,
0,
&newolp.ol,
NULL);
if (ret == SOCKET_ERROR)
{
if (WSAGetLastError() != WSA_IO_PENDING)
{
// Error
}
}
// Put structure in look aside list for later use
FreeOverlappedPlus(OverlapPlus);
// Signal accept thread to issue another AcceptEx
SetEvent(hAcceptThread);
break;
case OP_READ:
// Process the data read
// Repost the read if necessary, reusing the same
// receive buffer as before
memset(&OverlapPlus->ol, 0, sizeof(OVERLAPPED));
ret = WSARecv(
OverlapPlus->s,
&OverlapPlus->wbuf,
1,
&OverlapPlus->dwBytes,
&OverlapPlus->dwFlags,
&OverlapPlus->ol,
NULL);
if (ret == SOCKET_ERROR)
{
if (WSAGetLastError() != WSA_IO_PENDING)
{
// Error
}
}
break;
case OP_WRITE:
// Process the data sent, etc.
break;
} // switch
} // while
} // WorkerThread
銆
鏌ョ湅浠ヤ笂浠g爜錛屾敞鎰忓鏋淥verlapped鎿嶄綔绔嬪埢澶辮觸錛堟瘮濡傦紝榪斿洖SOCKET_ERROR鎴栧叾浠栭潪WSA_IO_PENDING鐨勯敊璇級錛屽垯 娌℃湁浠諱綍瀹屾垚閫氱煡鏃墮棿浼氳鏀懼埌瀹屾垚绔彛闃熷垪閲屻傚弽涔嬶紝鍒欎竴瀹氭湁鐩稿簲鐨勯氱煡鏃墮棿琚斁鍒板畬鎴愮鍙i槦鍒椼傛洿瀹屽杽鐨勫叧浜嶹insock鐨勫畬鎴愮鍙f満鍒訛紝鍙互鍙傝? MSDN鐨凪icrosoft PlatFormSDK錛岄偅閲屾湁瀹屾垚绔彛鐨勪緥瀛愩傝闂?a >http://msdn.microsoft.com/library/techart/msdn_servrapp.htm鍙互鑾峰緱鏇村淇℃伅銆?/p>
Linux鐨凟Poll妯″瀷
Linux 2.6鍐呮牳涓彁楂樼綉緇淚/O鎬ц兘鐨勬柊鏂規(guī)硶-epoll I/O澶氳礬澶嶇敤鎶鏈湪姣旇緝澶氱殑TCP緗戠粶鏈嶅姟鍣ㄤ腑鏈変嬌鐢紝鍗蟲瘮杈冨鐨勭敤鍒皊elect鍑芥暟銆?br>
1銆佷負浠涔坰elect钀藉悗
棣栧厛錛屽湪Linux鍐呮牳涓紝select鎵鐢ㄥ埌鐨凢D_SET鏄湁闄愮殑錛屽嵆鍐呮牳涓湁涓弬鏁癬_FD_SETSIZE瀹氫箟浜嗘瘡涓狥D_SET鐨勫彞鏌勪釜鏁幫紝鍦ㄦ垜鐢ㄧ殑2.6.15-25-386鍐呮牳涓紝璇ュ兼槸1024錛屾悳绱㈠唴鏍告簮浠g爜寰楀埌錛?br>include/linux/posix_types.h:#define __FD_SETSIZE 1024
涔?
灝辨槸璇達紝濡傛灉鎯寵鍚屾椂媯嫻?025涓彞鏌勭殑鍙鐘舵佹槸涓嶅彲鑳界敤select瀹炵幇鐨勩傛垨鑰呭悓鏃舵嫻?025涓彞鏌勭殑鍙啓鐘舵佷篃鏄笉鍙兘鐨勩傚叾嬈★紝鍐呮牳涓疄鐜?
select鏄敤杞鏂規(guī)硶錛屽嵆姣忔媯嫻嬮兘浼氶亶鍘嗘墍鏈塅D_SET涓殑鍙ユ焺錛屾樉鐒訛紝select鍑芥暟鎵ц鏃墮棿涓嶧D_SET涓殑鍙ユ焺涓暟鏈変竴涓瘮渚嬪叧緋伙紝鍗?
select瑕佹嫻嬬殑鍙ユ焺鏁拌秺澶氬氨浼氳秺璐規(guī)椂銆傚綋鐒訛紝鍦ㄥ墠鏂囦腑鎴戝茍娌℃湁鎻愬強poll鏂規(guī)硶錛屼簨瀹炰笂鐢╯elect鐨勬湅鍙嬩竴瀹氫篃璇曡繃poll錛屾垜涓漢瑙夊緱
select鍜宲oll澶у悓灝忓紓錛屼釜浜哄亸濂戒簬鐢╯elect鑰屽凡銆?/p>
2銆佸唴鏍鎬腑鎻愰珮I(yè)/O鎬ц兘鐨勬柊鏂規(guī)硶epoll
epoll鏄粈涔堬紵鎸夌収man鎵嬪唽鐨勮娉曪細鏄負澶勭悊澶ф壒閲忓彞鏌勮屼綔浜嗘敼榪涚殑poll銆傝浣跨敤epoll鍙渶瑕佽繖涓変釜緋葷粺璋冪敤錛歟poll_create(2)錛?epoll_ctl(2)錛?epoll_wait(2)銆?br>褰撶劧錛岃繖涓嶆槸2.6鍐呮牳鎵嶆湁鐨勶紝瀹冩槸鍦?.5.44鍐呮牳涓寮曡繘鐨?epoll(4) is a new API introduced in Linux kernel 2.5.44)
Linux2.6鍐呮牳epoll浠嬬粛 epoll_wait鑼冨洿涔嬪悗搴旇鏄竴涓驚鐜紝閬嶅埄鎵鏈夌殑浜嬩歡錛? 瀵癸紝epoll鐨勬搷浣滃氨榪欎箞綆鍗曪紝鎬誨叡涓嶈繃4涓狝PI錛歟poll_create, epoll_ctl, epoll_wait鍜宑lose銆? while (TRUE) OnWriteEpoll (i);//鏌ョ湅褰撳墠鐨勬椿鍔ㄨ繛鎺ユ槸鍚︽湁闇瑕佸啓鍑虹殑鏁版嵁銆?br>}
鍏堜粙緇?鏈功銆奣he Linux Networking
Architecture--Design and Implementation of Network Protocols in the
Linux Kernel銆嬶紝浠?.4鍐呮牳璁茶ВLinux
TCP/IP瀹炵幇錛岀浉褰撲笉閿?浣滀負涓涓幇瀹炰笘鐣屼腑鐨勫疄鐜幫紝寰堝鏃跺欎綘蹇呴』浣滃緢澶氭潈琛★紝榪欐椂鍊欏弬鑰冧竴涓箙緇忚冮獙鐨勭郴緇熸洿鏈夊疄闄呮剰涔夈備婦涓緥瀛?linux鍐?
鏍鎬腑sk_buff緇撴瀯涓轟簡榪芥眰閫熷害鍜屽畨鍏紝鐗虹壊浜嗛儴鍒嗗唴瀛橈紝鎵浠ュ湪鍙戦乀CP鍖呯殑鏃跺欙紝鏃犺搴旂敤灞傛暟鎹澶?sk_buff鏈灝忎篃鏈?72鐨勫瓧鑺?鍏跺疄
瀵逛簬socket搴旂敤灞傜▼搴忔潵璇達紝鍙﹀涓鏈功銆奤NIX Network Programming Volume
1銆嬫剰涔夋洿澶т竴鐐?2003騫寸殑鏃跺欙紝榪欐湰涔﹀嚭浜嗘渶鏂扮殑絎?鐗堟湰錛屼笉榪囦富瑕佽繕鏄慨璁㈢2鐗堟湰銆傚叾涓6绔犮奍/O
Multiplexing銆嬫槸鏈閲嶈鐨勩係tevens緇欏嚭浜嗙綉緇淚O鐨勫熀鏈ā鍨嬨傚湪榪欓噷鏈閲嶈鐨勮帿榪囦簬select妯″瀷鍜孉synchronous
I/O妯″瀷.浠庣悊璁轟笂璇達紝AIO浼間箮鏄渶楂樻晥鐨勶紝浣犵殑IO鎿嶄綔鍙互绔嬪嵆榪斿洖錛岀劧鍚庣瓑寰卭s鍛婅瘔浣營O鎿嶄綔瀹屾垚銆備絾鏄竴鐩翠互鏉ワ紝濡備綍瀹炵幇灝辨病鏈変竴涓畬緹庣殑鏂?
妗堛傛渶钁楀悕鐨剋indows瀹屾垚绔彛瀹炵幇鐨凙IO,瀹為檯涓婁篃鏄唴閮ㄧ敤綰跨▼姹犲疄鐜扮殑緗簡錛屾渶鍚庣殑緇撴灉鏄疘O鏈変釜綰跨▼姹狅紝浣犲簲鐢ㄤ篃闇瑕佷竴涓嚎紼嬫睜......
寰堝鏂囨。鍏跺疄宸茬粡鎸囧嚭浜嗚繖甯︽潵鐨勭嚎紼媍ontext-switch甯︽潵鐨勪唬浠楓傚湪linux
騫沖彴涓婏紝鍏充簬緗戠粶AIO涓鐩存槸鏀瑰姩鏈澶氱殑鍦版柟錛?.4鐨勫勾浠e氨鏈夊緢澶欰IO鍐呮牳patch,鏈钁楀悕鐨勫簲璇ョ畻鏄疭GI閭d釜銆備絾鏄竴鐩村埌2.6鍐呮牳鍙戝竷錛岀綉緇?
妯″潡鐨凙IO涓鐩存病鏈夎繘鍏ョǔ瀹氬唴鏍哥増鏈?澶ч儴鍒嗛兘鏄嬌鐢ㄧ敤鎴風嚎紼嬫ā鎷熸柟娉曪紝鍦ㄤ嬌鐢ㄤ簡NPTL鐨刲inux涓婇潰鍏跺疄鍜寃indows鐨勫畬鎴愮鍙e熀鏈笂宸笉澶?
浜?銆?.6鍐呮牳鎵鏀寔鐨凙IO鐗規(guī)寚紓佺洏鐨凙IO---鏀寔io_submit(),io_getevents()浠ュ強瀵笵irect
IO鐨勬敮鎸?灝辨槸緇曡繃VFS緋葷粺buffer鐩存帴鍐欑‖鐩橈紝瀵逛簬嫻佹湇鍔″櫒鍦ㄥ唴瀛樺鉤紼蟲т笂鏈夌浉褰撳府鍔?銆?br>鎵浠ワ紝鍓╀笅鐨剆elect妯″瀷鍩烘湰涓婂氨鏄垜浠?
鍦╨inux涓婇潰鐨勫敮涓閫夋嫨錛屽叾瀹烇紝濡傛灉鍔犱笂no-block
socket鐨勯厤緗紝鍙互瀹屾垚涓涓?浼?AIO鐨勫疄鐜幫紝鍙笉榪囨帹鍔ㄥ姏鍦ㄤ簬浣犺屼笉鏄痮s鑰屽凡銆備笉榪囦紶緇熺殑select/poll鍑芥暟鏈夌潃涓浜涙棤娉曞繊鍙楃殑緙?
鐐癸紝鎵浠ユ敼榪涗竴鐩存槸2.4-2.5寮鍙戠増鏈唴鏍哥殑浠誨姟錛屽寘鎷?dev/poll錛宺ealtime signal絳夌瓑銆傛渶緇堬紝Davide
Libenzi寮鍙戠殑epoll榪涘叆2.6鍐呮牳鎴愪負姝e紡鐨勮В鍐蟲柟妗?br>
3銆乪poll鐨勪紭鐐?/strong>
<1>鏀寔涓涓繘紼嬫墦寮澶ф暟鐩殑socket鎻忚堪絎?FD)
select
鏈涓嶈兘蹇嶅彈鐨勬槸涓涓繘紼嬫墍鎵撳紑鐨凢D鏄湁涓瀹氶檺鍒剁殑錛岀敱FD_SETSIZE璁劇疆錛岄粯璁ゅ兼槸2048銆傚浜庨偅浜涢渶瑕佹敮鎸佺殑涓婁竾榪炴帴鏁扮洰鐨処M鏈嶅姟鍣ㄦ潵璇存樉
鐒跺お灝戜簡銆傝繖鏃跺欎綘涓鏄彲浠ラ夋嫨淇敼榪欎釜瀹忕劧鍚庨噸鏂扮紪璇戝唴鏍革紝涓嶈繃璧勬枡涔熷悓鏃舵寚鍑鴻繖鏍蜂細甯︽潵緗戠粶鏁堢巼鐨勪笅闄嶏紝浜屾槸鍙互閫夋嫨澶氳繘紼嬬殑瑙e喅鏂規(guī)(浼犵粺鐨?
Apache鏂規(guī))錛屼笉榪囪櫧鐒秎inux涓婇潰鍒涘緩榪涚▼鐨勪唬浠鋒瘮杈冨皬錛屼絾浠嶆棫鏄笉鍙拷瑙嗙殑錛屽姞涓婅繘紼嬮棿鏁版嵁鍚屾榪滄瘮涓嶄笂綰跨▼闂村悓姝ョ殑楂樻晥錛屾墍浠ヤ篃涓嶆槸涓縐嶅畬
緹庣殑鏂規(guī)銆備笉榪?
epoll鍒欐病鏈夎繖涓檺鍒訛紝瀹冩墍鏀寔鐨凢D涓婇檺鏄渶澶у彲浠ユ墦寮鏂囦歡鐨勬暟鐩紝榪欎釜鏁板瓧涓鑸繙澶т簬2048,涓句釜渚嬪瓙,鍦?GB鍐呭瓨鐨勬満鍣ㄤ笂澶х害鏄?0涓囧乏
鍙籌紝鍏蜂綋鏁扮洰鍙互cat /proc/sys/fs/file-max瀵熺湅,涓鑸潵璇磋繖涓暟鐩拰緋葷粺鍐呭瓨鍏崇郴寰堝ぇ銆?br><2>IO鏁堢巼涓嶉殢FD鏁扮洰澧炲姞鑰岀嚎鎬т笅闄?br>浼?
緇熺殑select/poll鍙︿竴涓嚧鍛藉急鐐瑰氨鏄綋浣犳嫢鏈変竴涓緢澶х殑socket闆嗗悎錛屼笉榪囩敱浜庣綉緇滃歡鏃訛紝浠諱竴鏃墮棿鍙湁閮ㄥ垎鐨剆ocket鏄?媧昏穬"鐨勶紝浣?
鏄痵elect/poll姣忔璋冪敤閮戒細綰挎ф壂鎻忓叏閮ㄧ殑闆嗗悎錛屽鑷存晥鐜囧憟鐜扮嚎鎬т笅闄嶃備絾鏄痚poll涓嶅瓨鍦ㄨ繖涓棶棰橈紝瀹冨彧浼氬"媧昏穬"鐨剆ocket榪涜鎿?
浣?--榪欐槸鍥犱負鍦ㄥ唴鏍稿疄鐜頒腑epoll鏄牴鎹瘡涓猣d涓婇潰鐨刢allback鍑芥暟瀹炵幇鐨勩傞偅涔堬紝鍙湁"媧昏穬"鐨剆ocket鎵嶄細涓誨姩鐨勫幓璋冪敤
callback鍑芥暟錛屽叾浠杋dle鐘舵乻ocket鍒欎笉浼氾紝鍦ㄨ繖鐐逛笂錛宔poll瀹炵幇浜嗕竴涓?浼?AIO錛屽洜涓鴻繖鏃跺欐帹鍔ㄥ姏鍦╫s鍐呮牳銆傚湪涓浜?
benchmark涓紝濡傛灉鎵鏈夌殑socket鍩烘湰涓婇兘鏄椿璺冪殑---姣斿涓涓珮閫烲AN鐜錛宔poll騫朵笉姣攕elect/poll鏈変粈涔堟晥鐜囷紝鐩?
鍙嶏紝濡傛灉榪囧浣跨敤epoll_ctl,鏁堢巼鐩告瘮榪樻湁紼嶅井鐨勪笅闄嶃備絾鏄竴鏃︿嬌鐢╥dle
connections妯℃嫙WAN鐜,epoll鐨勬晥鐜囧氨榪滃湪select/poll涔嬩笂浜嗐?br><3>浣跨敤mmap鍔犻熷唴鏍鎬笌鐢ㄦ埛絀洪棿鐨勬秷鎭紶閫掋?br>榪?
鐐瑰疄闄呬笂娑夊強鍒癳poll鐨勫叿浣撳疄鐜頒簡銆傛棤璁烘槸select,poll榪樻槸epoll閮介渶瑕佸唴鏍告妸FD娑堟伅閫氱煡緇欑敤鎴風┖闂達紝濡備綍閬垮厤涓嶅繀瑕佺殑鍐呭瓨鎷瘋礉灝卞緢
閲嶈錛屽湪榪欑偣涓婏紝epoll鏄氳繃鍐呮牳浜庣敤鎴風┖闂磎map鍚屼竴鍧楀唴瀛樺疄鐜扮殑銆傝屽鏋滀綘鎯蟲垜涓鏍蜂粠2.5鍐呮牳灝卞叧娉╡poll鐨勮瘽錛屼竴瀹氫笉浼氬繕璁版墜宸?
mmap榪欎竴姝ョ殑銆?br><4>鍐呮牳寰皟
榪欎竴鐐瑰叾瀹炰笉綆梕poll鐨勪紭鐐逛簡錛岃屾槸鏁翠釜linux騫沖彴鐨勪紭鐐廣備篃璁鎬綘鍙互鎬鐤?
linux騫沖彴錛屼絾鏄綘鏃犳硶鍥為伩linux騫沖彴璧嬩簣浣犲井璋冨唴鏍哥殑鑳藉姏銆傛瘮濡傦紝鍐呮牳TCP/IP鍗忚鏍堜嬌鐢ㄥ唴瀛樻睜綆$悊sk_buff緇撴瀯錛岄偅涔堝彲浠ュ湪榪愯鏃?
鏈熷姩鎬佽皟鏁磋繖涓唴瀛榩ool(skb_head_pool)鐨勫ぇ灝?-- 閫氳繃echo
XXXX>/proc/sys/net/core/hot_list_length瀹屾垚銆傚啀姣斿listen鍑芥暟鐨勭2涓弬鏁?TCP瀹屾垚3嬈℃彙鎵?
鐨勬暟鎹寘闃熷垪闀垮害)錛屼篃鍙互鏍規(guī)嵁浣犲鉤鍙板唴瀛樺ぇ灝忓姩鎬佽皟鏁淬傛洿鐢氳嚦鍦ㄤ竴涓暟鎹寘闈㈡暟鐩法澶т絾鍚屾椂姣忎釜鏁版嵁鍖呮湰韜ぇ灝忓嵈寰堝皬鐨勭壒孌婄郴緇熶笂灝濊瘯鏈鏂扮殑NAPI緗?
鍗¢┍鍔ㄦ灦鏋勩?br>4銆乪poll鐨勫伐浣滄ā寮?br>浠や漢楂樺叴鐨勬槸錛?.6鍐呮牳鐨別poll姣斿叾2.5寮鍙戠増鏈殑/dev/epoll綆媧佷簡璁稿錛屾墍浠ワ紝澶ч儴鍒嗘儏鍐典笅錛屽己澶х殑涓滆タ寰寰鏄畝鍗曠殑銆傚敮涓鏈夌偣楹葷儲鏄痚poll鏈?縐嶅伐浣滄柟寮?LT鍜孍T銆?br>LT(level
triggered)鏄己鐪佺殑宸ヤ綔鏂瑰紡錛屽茍涓斿悓鏃舵敮鎸乥lock鍜宯o-block
socket.鍦ㄨ繖縐嶅仛娉曚腑錛屽唴鏍稿憡璇変綘涓涓枃浠舵弿榪扮鏄惁灝辯華浜嗭紝鐒跺悗浣犲彲浠ュ榪欎釜灝辯華鐨刦d榪涜IO鎿嶄綔銆傚鏋滀綘涓嶄綔浠諱綍鎿嶄綔錛屽唴鏍歌繕鏄細緇х畫閫氱煡浣?
鐨勶紝鎵浠ワ紝榪欑妯″紡緙栫▼鍑洪敊璇彲鑳芥ц灝忎竴鐐廣備紶緇熺殑select/poll閮芥槸榪欑妯″瀷鐨勪唬琛紟
ET
(edge-triggered)鏄珮閫熷伐浣滄柟寮忥紝鍙敮鎸乶o-block
socket銆傚湪榪欑妯″紡涓嬶紝褰撴弿榪扮浠庢湭灝辯華鍙樹負灝辯華鏃訛紝鍐呮牳閫氳繃epoll鍛婅瘔浣犮傜劧鍚庡畠浼氬亣璁句綘鐭ラ亾鏂囦歡鎻忚堪絎﹀凡緇忓氨緇紝騫朵笖涓嶄細鍐嶄負閭d釜鏂囦歡鎻忚堪
絎﹀彂閫佹洿澶氱殑灝辯華閫氱煡錛岀洿鍒頒綘鍋氫簡鏌愪簺鎿嶄綔瀵艱嚧閭d釜鏂囦歡鎻忚堪絎︿笉鍐嶄負灝辯華鐘舵佷簡(姣斿錛屼綘鍦ㄥ彂閫侊紝鎺ユ敹鎴栬呮帴鏀惰姹傦紝鎴栬呭彂閫佹帴鏀剁殑鏁版嵁灝戜簬涓瀹氶噺鏃跺鑷?
浜嗕竴涓狤WOULDBLOCK 閿欒錛夈備絾鏄娉ㄦ剰錛屽鏋滀竴鐩翠笉瀵硅繖涓猣d浣淚O鎿嶄綔(浠庤屽鑷村畠鍐嶆鍙樻垚鏈氨緇?錛屽唴鏍鎬笉浼氬彂閫佹洿澶氱殑閫氱煡(only
once),涓嶈繃鍦═CP鍗忚涓紝ET妯″紡鐨勫姞閫熸晥鐢ㄤ粛闇瑕佹洿澶氱殑benchmark紜銆?br>epoll鍙湁epoll_create,epoll_ctl,epoll_wait 3涓郴緇熻皟鐢紝鍏蜂綋鐢ㄦ硶璇峰弬鑰?a >http://www.xmailserver.org/linux-patches/nio-improve.html 錛屽湪http://www.kegel.com/rn/涔熸湁涓涓畬鏁寸殑渚嬪瓙錛屽ぇ瀹朵竴鐪嬪氨鐭ラ亾濡備綍浣跨敤浜?br>Leader/follower妯″紡綰跨▼pool瀹炵幇錛屼互鍙婂拰epoll鐨勯厤鍚堛?br>
5銆?epoll鐨勪嬌鐢ㄦ柟娉?/strong>
棣栧厛閫氳繃create_epoll(int
maxfds)鏉ュ垱寤轟竴涓猠poll鐨勫彞鏌勶紝鍏朵腑maxfds涓轟綘epoll鎵鏀寔鐨勬渶澶у彞鏌勬暟銆傝繖涓嚱鏁頒細榪斿洖涓涓柊鐨別poll鍙ユ焺錛屼箣鍚庣殑鎵鏈夋搷浣?
灝嗛氳繃榪欎釜鍙ユ焺鏉ヨ繘琛屾搷浣溿傚湪鐢ㄥ畬涔嬪悗錛岃寰楃敤close()鏉ュ叧闂繖涓垱寤哄嚭鏉ョ殑epoll鍙ユ焺銆?
涔嬪悗鍦ㄤ綘鐨勭綉緇滀富寰幆閲岄潰錛屾瘡涓甯х殑璋冪敤epoll_wait(int epfd, epoll_event events, int max
events, int timeout)鏉ユ煡璇㈡墍鏈夌殑緗戠粶鎺ュ彛錛岀湅鍝竴涓彲浠ヨ錛屽摢涓涓彲浠ュ啓浜嗐傚熀鏈殑璇硶涓猴細
nfds = epoll_wait(kdpfd, events, maxevents, -1);
鍏?
涓璳dpfd涓虹敤epoll_create鍒涘緩涔嬪悗鐨勫彞鏌勶紝events鏄竴涓猠poll_event*鐨勬寚閽堬紝褰揺poll_wait榪欎釜鍑芥暟鎿嶄綔鎴愬姛
涔嬪悗錛宔poll_events閲岄潰灝嗗偍瀛樻墍鏈夌殑璇誨啓浜嬩歡銆俶ax_events鏄綋鍓嶉渶瑕佺洃鍚殑鎵鏈塻ocket鍙ユ焺鏁般傛渶鍚庝竴涓猼imeout鏄?
epoll_wait鐨勮秴鏃訛紝涓?鐨勬椂鍊欒〃紺洪┈涓婅繑鍥烇紝涓?1鐨勬椂鍊欒〃紺轟竴鐩寸瓑涓嬪幓錛岀洿鍒版湁浜嬩歡鑼冨洿錛屼負浠繪剰姝f暣鏁扮殑鏃跺欒〃紺虹瓑榪欎箞闀跨殑鏃墮棿錛屽鏋滀竴鐩存病
鏈変簨浠訛紝鍒欒寖鍥淬備竴鑸鏋滅綉緇滀富寰幆鏄崟鐙殑綰跨▼鐨勮瘽錛屽彲浠ョ敤-1鏉ョ瓑錛岃繖鏍峰彲浠ヤ繚璇佷竴浜涙晥鐜囷紝濡傛灉鏄拰涓婚昏緫鍦ㄥ悓涓涓嚎紼嬬殑璇濓紝鍒欏彲浠ョ敤0鏉ヤ繚璇佷富寰幆
鐨勬晥鐜囥?/p>
for(n = 0; n < nfds; ++n) {
if(events[n].data.fd == listener) { //濡傛灉鏄富socket鐨勪簨浠剁殑璇濓紝鍒欒〃紺烘湁鏂拌繛鎺ヨ繘鍏ヤ簡錛岃繘琛屾柊榪炴帴鐨勫鐞嗐?
client = accept(listener, (struct sockaddr *) &local,
&addrlen);
if(client < 0){
perror("accept");
continue;
}
setnonblocking(client); // 灝嗘柊榪炴帴緗簬闈為樆濉炴ā寮?
ev.events = EPOLLIN | EPOLLET; // 騫朵笖灝嗘柊榪炴帴涔熷姞鍏POLL鐨勭洃鍚槦鍒椼?
娉ㄦ剰錛岃繖閲岀殑鍙傛暟EPOLLIN | EPOLLET騫舵病鏈夎緗鍐檚ocket鐨勭洃鍚紝濡傛灉鏈夊啓鎿嶄綔鐨勮瘽錛岃繖涓椂鍊檈poll鏄笉浼氳繑鍥炰簨浠剁殑錛屽鏋滆瀵瑰啓鎿嶄綔涔熺洃鍚殑璇濓紝搴旇鏄疎POLLIN | EPOLLOUT | EPOLLET
ev.data.fd = client;
if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, client, &ev) < 0) {
//
璁劇疆濂絜vent涔嬪悗錛屽皢榪欎釜鏂扮殑event閫氳繃epoll_ctl鍔犲叆鍒癳poll鐨勭洃鍚槦鍒楅噷闈紝榪欓噷鐢‥POLL_CTL_ADD鏉ュ姞涓涓柊鐨?
epoll浜嬩歡錛岄氳繃EPOLL_CTL_DEL鏉ュ噺灝戜竴涓猠poll浜嬩歡錛岄氳繃EPOLL_CTL_MOD鏉ユ敼鍙樹竴涓簨浠剁殑鐩戝惉鏂瑰紡銆?
fprintf(stderr, "epoll set insertion error: fd=%d0,
client);
return -1;
}
}
else // 濡傛灉涓嶆槸涓籹ocket鐨勪簨浠剁殑璇濓紝鍒欎唬琛ㄦ槸涓涓敤鎴穝ocket鐨勪簨浠訛紝鍒欐潵澶勭悊榪欎釜鐢ㄦ埛socket鐨勪簨鎯咃紝姣斿璇磖ead(fd,xxx)涔嬬被鐨勶紝鎴栬呬竴浜涘叾浠栫殑澶勭悊銆?
do_use_fd(events[n].data.fd);
}
濡傛灉鎮(zhèn)ㄥepoll鐨勬晥鐜囪繕涓嶅お浜嗚В錛岃鍙傝冩垜涔嬪墠鍏充簬緗戠粶娓告垙鐨勭綉緇滅紪紼嬬瓑鐩稿叧鐨勬枃绔犮?/p>
浠ュ墠鍏徃鐨勬湇鍔″櫒閮芥槸浣跨敤HTTP榪炴帴錛屼絾鏄繖鏍風殑璇濓紝鍦ㄦ墜鏈虹洰鍓嶇殑緗戠粶鎯呭喌涓嬩笉浣嗘樉寰楅熷害杈冩參錛岃屼笖涓嶇ǔ瀹氥傚洜姝ゅぇ瀹朵竴鑷村悓鎰忕敤
SOCKET鏉ヨ繘琛岃繛鎺ャ傝櫧鐒朵嬌鐢⊿OCKET涔嬪悗錛屽浜庣敤鎴風殑璐圭敤鍙兘浼氬鍔?鐢變簬鏄敤浜咰MNET鑰岄潪CMWAP)錛屼絾鏄紝縐夌潃鐢ㄦ埛浣撻獙鑷充笂鐨勫師鍒欙紝
鐩鎬俊澶у榪樻槸鑳藉鎺ュ彈鐨?甯屾湜閭d簺鐜╁鏈堟湯鏀跺埌甯愬崟涓嶅悗鑳藉淇濇寔鍏嬪埗...)銆?br>榪欐鐨勬湇鍔″櫒璁捐涓紝鏈閲嶈鐨勪竴涓獊鐮達紝鏄嬌鐢ㄤ簡EPOLL妯″瀷錛岃櫧鐒跺涔嬩篃鏄竴鐭ュ崐瑙o紝浣嗘槸鏃㈢劧鍦ㄥ悇澶C緗戞父涓凡緇忕粡榪囦簡濡傛涓ラ叿鐨勮冮獙錛岀浉淇′粬涓嶄細璁╂垜浠け鏈涳紝浣跨敤鍚庣殑緇撴灉錛岀‘瀹炰篃鏄〃鐜扮浉褰撲笉閿欍傚湪榪欓噷錛屾垜榪樻槸涓昏澶ц嚧浠嬬粛涓涓嬭繖涓ā鍨嬬殑緇撴瀯銆?br>6銆丩inux涓婨POll緙栫▼瀹炰緥
EPOLL妯″瀷浼間箮鍙湁涓縐嶆牸寮忥紝鎵浠ュぇ瀹跺彧瑕佸弬鑰冩垜涓嬮潰鐨勪唬鐮侊紝灝辮兘澶熷EPOLL鏈夋墍浜嗚В浜嗭紝浠g爜鐨勮В閲婇兘宸茬粡鍦ㄦ敞閲婁腑錛?/p>
{
int nfds = epoll_wait (m_epoll_fd, m_events, MAX_EVENTS, EPOLL_TIME_OUT);//絳夊緟EPOLL鏃墮棿鐨勫彂鐢燂紝鐩稿綋浜庣洃鍚紝鑷充簬鐩稿叧鐨勭鍙o紝闇瑕佸湪鍒濆鍖朎POLL鐨勬椂鍊欑粦瀹氥?br>if (nfds <= 0)
continue;
m_bOnTimeChecking = FALSE;
G_CurTime = time(NULL);
for (int i=0; i
{
try
{
if (m_events[i].data.fd == m_listen_http_fd)//濡傛灉鏂扮洃嫻嬪埌涓涓狧TTP鐢ㄦ埛榪炴帴鍒扮粦瀹氱殑HTTP绔彛錛屽緩绔嬫柊鐨勮繛鎺ャ傜敱浜庢垜浠柊閲囩敤浜哠OCKET榪炴帴錛屾墍浠ュ熀鏈病鐢ㄣ?br>{
OnAcceptHttpEpoll ();
}
else if (m_events[i].data.fd == m_listen_sock_fd)//濡傛灉鏂扮洃嫻嬪埌涓涓猄OCKET鐢ㄦ埛榪炴帴鍒頒簡緇戝畾鐨凷OCKET绔彛錛屽緩绔嬫柊鐨勮繛鎺ャ?br>{
OnAcceptSockEpoll ();
}
else if (m_events[i].events & EPOLLIN)//濡傛灉鏄凡緇忚繛鎺ョ殑鐢ㄦ埛錛屽茍涓旀敹鍒版暟鎹紝閭d箞榪涜璇誨叆銆?br>{
OnReadEpoll (i);
}
catch (int)
{
PRINTF ("CATCH鎹曡幏閿欒\n");
continue;
}
}
m_bOnTimeChecking = TRUE;
OnTimer ();//榪涜涓浜涘畾鏃剁殑鎿嶄綔錛屼富瑕佸氨鏄垹闄や竴浜涚煭綰跨敤鎴風瓑銆?br>}
銆鍏跺疄EPOLL鐨勭簿鍗庯紝涔熷氨鏄笂榪扮殑鍑犳鐭煭鐨勪唬鐮侊紝鐪嬫潵鏃朵唬鐪熺殑涓嶅悓浜嗭紝浠ュ墠濡備綍鎺ュ彈澶ч噺鐢ㄦ埛榪炴帴鐨勯棶棰橈紝鐜板湪鍗磋濡傛杞繪澗鐨勬悶瀹氾紝鐪熸槸璁╀漢涓嶅緱涓嶆劅鍙癸紝瀵瑰摢銆?/p>
鎬葷粨
Windows瀹屾垚绔彛涓嶭inux epoll鎶鏈柟妗堟槸榪?涓鉤鍙頒笂瀹炵幇寮傛IO鍜岃璁″紑鍙戜竴涓ぇ瀹歸噺錛屽叿鍙墿灞曟х殑winsock紼嬪簭鎸囨湇鍔$▼搴忕殑寰堝ソ鐨勯夋嫨錛屾湰鏂囧榪?涓妧鏈殑瀹炵幇鍘熺悊鍜屽疄闄呯殑浣跨敤鏂規(guī)硶鍋氫簡涓涓緇嗙殑浠嬬粛銆?/p>