2019独角兽企业重金招聘Python工程师标准>>>

在《 modb 功能设计之“支持多消费者单生产者” 》中曾提到,需要解决“rabbitmq 线程与 sql 执行线程之间的跨线程通信手段”。本文针对这个问题进行一些说明。

【第一个版本】
      使用 pipe 作为跨线程通信方式,使用如下代码来支持 pipe:

# 使用 _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” 报出。最终查出的结论是:

WSAENOTSOCK                    (10038)             Socket operation on non-socket.

操作试图不是在套接字上进行。它可能是套接字句柄参数没有引用到一个合法套接字,或者是调用 select() 函数时,一个 fd_set 中的成员不合法。

查来查去,结果发现,就是 windows 下不能将 pipe(其实是 _pipe)和 select 一起使用的原因。因为 windows 平台上会认为 pipe 产生的 fd 不是一个合法的 socket 句柄,在将读端 fds[0] 添加进 libevent 进行可读监听后(在 windows 平台下 libevent 使用 select 进行 fd 的检测),就会报出上面的 “10038” 错误;与此对应的,linux 下认为“一切皆文件”,所以是没有这个问题的。这让我再一次鄙视了 MS Windows。

_pipe() 的实现如下:

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 了,备选方案如下:

  1. 通过 socket 模拟 pipe 的实现
  2. 使用 socketpair 实现(同样是通过 socket 来模拟 unix 下的 socketpair)

PS:另外一个出现的错误情况是,windows 下再调用 select() 前,需要先调用 WSAStartup(),否则会报出 “10093” 错误。

WSANOTINITIALISED           (10093)             Successful WSAStartup() not yet performed.

应用程序没有调用 WSAStartup() 函数,或函数 WSAStartup() 调用失败了。应用程序可能访问了不属于当前活动任务的套接字(例如试图在任务间共享套接字),或调用了过多的 WSACleanup() 函数。

【第二个版本】
      翻阅大量开源软件的代码后,经过 对比发现后发现,两者的实现代码基本相同,只是名字不同而已。换句话说,通过 socket 模拟出来的这个东东,既可以替代 pipe(通常用于具有父子关系的进程间通信)的功能,也可以替代 socketpair(通常用于 AF_UNIX 域)的功能。

虽然上面说过,使用 socket 模拟 pipe 和模拟 socketpair 在代码实现上是没有差别的,但并不是说 linux 下的 pipe 和 socketpair 没有差别,所以下面的讨论以实现 pipe 为例。 具体代码可以参考我之前写过的一篇博客:《 MySQL Proxy中socketpair的使用 》。

在采用 socket 实现的 pipe 后,首先遇到的问题是,调用 write( sql_event_thread->notify_send_fd, "", 1 ) 会报如下断言错误:

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 ?这个值代表什么意思?(读者思考)

总之,结论表明在 windows 平台下,对 socket fd 直接进行 read/write 会有错误产生。 没办法还是换成标准的 socket 函数 send/recv 吧。

结果一切都 ok 了。

=== 未完待续 ===

转载于:https://my.oschina.net/moooofly/blog/184986

【原创】modb 功能设计之“跨线程通信”相关推荐

  1. ZeroMq实现跨线程通信

    ZeroMq实现跨线程通信 之前在技术崇拜的技术经理指导下阅读了ZeroMq的基础代码,现在就将阅读的心得与成果记录一下,并重新模仿实现了一下经理的异步队列. 1.对外接口 //主要接口(1)void ...

  2. EventBus,轻松实现跨组件跨线程通信

    安卓基础开发库,让开发简单点. DevRing & Demo地址:github.com/LJYcoder/De- 学习/参考地址: http://blog.csdn.net/itachi85/ ...

  3. js 原生跨页面通信_DOM操作是跨线程的你知道吗?

    在JS世界里面浏览器有两个重要的功能,分为渲染引擎和JS引擎.渲染引擎专门负责渲染Html和css的,JS引擎是专门用来执行JS的.这两个引擎是在不同的线程里面,它们都自己做着自己的事情,互不打扰. ...

  4. 【原创】modb 功能设计之“支持多消费者单生产者”

    2019独角兽企业重金招聘Python工程师标准>>> 在< modb 开发之需求和总体设计 >中,第一个要实现的功能点就是 "支持多消费者单生产者" ...

  5. Android的跨进程通信

    Android系统的跨进程简介 为什么不能直接跨进程通信? 为了安全考虑,应用之间的内存是无法互相访问的,各自的数据都存在于自身的内存区域内. 如何跨进程通信? 要想跨进程通信,就要找到一个大家都能访 ...

  6. Android 跨进程通信大总结

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/111553746 本文出自[赵彦军的博客] 文章目录 1.Android进程 2.修 ...

  7. Jmeter之Bean shell使用(四)——跨线程组之间的全局参数传递

    使用场景: 请求API需要授权令牌,但是授权令牌只需要获取一次,即可调用服务器上其他业务接口. 所以我想要把授权操作放在单独的一个线程,业务流放在其他线程. 这就需要我把从授权线程获取的令牌传入业务流 ...

  8. 多线程总结之旅(12):跨线程调用控件的几种方式

    本来是写完线程池就结束多线程总结之旅系列的,但是想想平时在项目中用到线程仅仅不够的,为什么这么说呢?举个例子:我们有一个函数,它的功能就是加载数据,然后绑定到datagridview.现在我们开启一个 ...

  9. C#中利用委托实现多线程跨线程操作

    在使用VS2005的时候,如果你从非创建这个控件的线程中访问这个控件或者操作这个控件的话就会抛出这个异常.这是微软为了保证线程安全以及提高代码的效率所做的改进,但是也给大家带来很多不便. 其实解决这个 ...

最新文章

  1. 第11章 UART 串口通信(手把手教你学51单片机pdf部分)
  2. Matplotlib使用scatter函数在Python中绘制气泡图(bubble plot)、通过size参数指定数据点的大小、自定义不同分组的气泡的色彩
  3. 20145240《信息安全系统设计基础》第十二周学习总结
  4. leetcode — maximum-subarray
  5. linux ssh免密登陆远程服务器
  6. 项目中的一个AOP的编写案例(配置+案例)
  7. win10无法查看计算机名,win10如何查看计算机名字
  8. Hive insert into小文件问题优化解决
  9. ASP.NET MVC Url中参数过长引发的问题
  10. 【VC皮肤】SkinSharp 1.0.6.6的使用
  11. excel报表导出功能
  12. 酷炫的迁徙图和轮播图,用pyecharts也可以做出来
  13. Docker下载redis镜像
  14. Photosho cs6安装字体教程
  15. 计算机中单位换算tb,计算机中容量单位B、KB、MB、GB和TB的关系
  16. 如何配置FMS边缘服务器
  17. 如何用CSS动画特效让图片旋转起来
  18. 傅连仲主编的《计算机应用基础》,学生教学论文,关于计算机应用基础课程标准研读的必要性相关参考文献资料-免费论文范文...
  19. 当WebRTC Pion示例无音频流的时候,如何添加音频模块并通过浏览器播放?
  20. html文本框如何固定不动,css如何让div固定不动?

热门文章

  1. Linux在后台运行python程序、脚本程序、可执行程序等,关闭终端仍可保持程序运行
  2. Linux命令行文档查看cat、less、more、head、tail和图片查看
  3. mybatis对mapper.xml的解析(二)
  4. 20180316 代码错题(1)
  5. Xshell连接不上Linux的解决方法
  6. TCP/IP协议学习之TCP、IP篇
  7. BinaryWriter和BinaryReader用法
  8. BestCoder Round #78 (div.2)
  9. SQLSERVER 2008 R2中的全文检索
  10. 浅谈创业性公司的发展