一个自用的进程间通信库(一)

来源:互联网 发布:北京java工资 编辑:程序博客网 时间:2024/06/01 14:06

         用过一些进程间通信的方法,总觉得用起来不是特别方便,要么步骤太多,要么库太大。于是决定给自己写个库,主要是想让自己在遇到进程间通信的时候能以更简便的方式使用,记录下来也是整理一下自己的思路。

       理想中的使用方法是:A进程注册一个进程名称A(信箱A),提供一个接收数据的处理函数,然后,然后就够了!B进程注册一个名称B(信箱B),对A发送数据,A的处理函数自动处理接收到的数据。最基本的使用方法一共只需要2个函数再加一个处理数据的回调函数应该就够了,用到的函数如下:

           int OpenLocalBox(const char* name,LOCALDATA_CALLBACK_FUNC func, int property);

           int SendNamedData(const char* dest, constchar* src, const ZLocalDataValue& val);

      这里LOCALDATA_CALLBACK_FUNC是处理数据的回调函数,ZLocalDataValue是发送数据的类型结构,包含一个char*数据指针字段和一个int型数据长度字段。

    除了以上的基本使用方法,这个库主要还想达到以下几个目标:

  1. 能支持windows和linux,桌面应用虽已没落,但是其它的不会啊,还得指望着c++和Qt混口饭吃啊;
  2. 便携式,在windows下就是一个dll文件,在linux下就是一个so文件,再加一个.h头文件。而且不依赖某一个开发包,这样的好处是用vc2010来调用能与已有的进程进行交互,用vc2015也可以,甚至用vc6也应该能行,MFC能用,Qt也能用,windows上能用,linux下也能用;
  3. 要有通知机制,发送端能用事件或者信号等手段通知接收端数据已到达,而无需接收端通过轮询这种低效率的方式来接收数据;
  4. 在可能的情况下尽量不限定发送包的数量和大小,就是传说中吹牛所说的随便发,怎么搞都能行,但绝对不能把系统搞死;
  5. 进程内不同模块之间的通信也能用,同一模块内还能用,同一进程内的通信不应影响到其它进程之间的通信;
  6. 某个进程非正常退出时不能影响其它进程间的数据交互,最好能提供额外的清理手段;
  7. 使用方便,争取几个C函数就把它给解决了;

       实现的基本原理其实很简单,就是开一块共享内存来自己管理,每个进程启动一个线程等待事件,发送进程发送完数据后把接收进程的事件置为有信号,windows下用SetEvent来发送事件,linux下用的是共享内存中的数据结构pthread_cond_signal,接收进程收到事件后在线程中开始检查所有的本地信箱。这里有个问题,事件无法告知接收进程数据发送到哪个信箱了,所以目前只能检查所有的本地信箱。本地线程收到数据后立即将数据拷贝到本地进程队列,这样可以减少锁定整个共享内存的时间(刚开始我是收到数据直接调用回调函数处理共享内存中的数据的,这样可以减少一次拷贝,但是如果处理函数的执行时间很长,比如执行数据库写入操作,那就坏事了,别的进程无法发送数据了,因为信箱的创建、数据包的发送、接收过程中目前都是锁定整个共享内存的)。将所有数据拷贝到本地后,解锁共享内存,然后调用数据处理函数处理本地拷贝的数据,处理掉一个删一个。

    先来看看windows下的测试程序,来一个Qt5+vs2013的,再来一个vc6+mfc的(久违了),能通吗?看结果!


       没有问题,左边的Qt5程序发送字符串"test0_00"~"test0_09"到右边的程序,右边的vc6程序发送字符串"ddddd"到左边的程序,双方在debug信息里面输出接收到的数据,而且代码就只需要那么几行。
       涉及到的头文件定义:
#define LOCALDATA_NAMELEN                   32struct ZLocalDataHead{    int                                     src_id;    int                                     dest_id;    int                                     src_pid;    int                                     dest_pid;    char                                    msg_timet[8];           //long long    char                                    src_name[LOCALDATA_NAMELEN];    char                                    dest_name[LOCALDATA_NAMELEN];};struct ZLocalDataValue{    char*                                   data;    int                                     len;};struct ZLocalDataPacket{    ZLocalDataHead                          header;    ZLocalDataValue                         value;};typedef void (*LOCALDATA_CALLBACK_FUNC)(const ZLocalDataPacket&);

好了,后面继续整理思路,记录实现方法......

原创粉丝点击