# 使用 _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