# 使用 _pipe 來模擬 pipe #if defined(WIN32) || defined(_WIN32) #include <io.h> #include <fcntl.h> #define pipe(fds) _pipe(fds, 4096, _O_BINARY) #endif
此時運行實現了 sql 線程的 demo,發現 sql 線程老是沒法正常運行,在調用 libevent 接口 event_base_dispatch 時會有錯誤 「10038」 報出。最終查出的結論是: linux
WSAENOTSOCK (10038) Socket operation on non-socket.
操做試圖不是在套接字上進行。它多是套接字句柄參數沒有引用到一個合法套接字,或者是調用 select() 函數時,一個 fd_set 中的成員不合法。 sql
查來查去,結果發現,就是 windows 下不能將 pipe(實際上是 _pipe)和 select 一塊兒使用的緣由。由於 windows 平臺上會認爲 pipe 產生的 fd 不是一個合法的 socket 句柄,在將讀端 fds[0] 添加進 libevent 進行可讀監聽後(在 windows 平臺下 libevent 使用 select 進行 fd 的檢測),就會報出上面的 「10038」 錯誤;與此對應的,linux 下認爲「一切皆文件」,因此是沒有這個問題的。這讓我再一次鄙視了 MS Windows。int __cdecl _pipe ( int phandles[2], unsigned psize, int textmode ) { int handle0, handle1; HANDLE ReadHandle, WriteHandle; ... if (!CreatePipe(&ReadHandle, &WriteHandle, &SecurityAttributes, psize)) { // 調用 win api 建立 pipe ... return -1; } /* now we must allocate C Runtime handles for Read and Write handles */ if ((handle0 = _alloc_osfhnd()) != -1) { // 獲取可用的 C 運行時句柄用做 pipe 的讀端 ... if ((handle1 = _alloc_osfhnd()) != -1) { // 獲取可用的 C 運行時句柄用做 pipe 的寫端 ... _set_osfhnd(handle0, (intptr_t)ReadHandle); // 將 CRT 文件句柄和 Win32 HANDLE 進行關聯 _set_osfhnd(handle1, (intptr_t)WriteHandle); } } ... phandles[0] = handle0; phandles[1] = handle1; return 0; }
沒辦法,由於有 windows 下調試的須要,既然在 windows 下沒法對非 socket fd 進行 select,那麼可選方案只有經過 socket 來實現 pipe 了,備選方案以下: shell
WSANOTINITIALISED (10093) Successful WSAStartup() not yet performed.
應用程序沒有調用 WSAStartup() 函數,或函數 WSAStartup() 調用失敗了。應用程序可能訪問了不屬於當前活動任務的套接字(例如試圖在任務間共享套接字),或調用了過多的 WSACleanup() 函數。 windows
vctools\crt_bld\self_x86\crt\src\write.c Line: 67 Expression: (fh >= 0 && (unsigned)fh < (unsigned)_nhandle)
其中 fh 爲程序建立的 socket 句柄的值(例如 12116),_nhandle 是系統定義值(發現其值爲 32)。 _nhandle 爲何是 32 ?這個值表明什麼意思?(讀者思考)
api