`
twu66twu
  • 浏览: 12472 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

进程间通信

 
阅读更多

进程间通信
2011年01月01日
  1、共享内存
  使用CreateFileMapping函数创建文件映射,指定第一个参数为INVALID_HANDLE_VALUE表明在系统页文件中开辟共享内存,最后一个参数指定文件映射的名字。
  使用MapViewOfFile将已创建的文件映射映射到当前进程地址空间,可以读写访问。
  另一个进程可以使用OpenFileMapping通过制定文件映射名字,打开一个已经创建的文件映射。
  使用MapViewOfFile将已创建的文件映射映射到当前进程地址空间,可以读写访问。
  这样两个进程都可以讲共享内存映射到自己的进程地址空间,进行通信。
  通信完毕后需要使用UnmapViewOfFile取消映射,CloseHandle销毁文件映射。
  只适用于同一机器上的进程间通信。
  写数据的进程: 
  
  #include 
  
  #include 
  
  #include 
  
  using namespace std;
  
  
  
  
  int main()
  
  {
  
  //创建文件映射,指向操作系统页面文件
  
  HANDLE hFileMapping = ::CreateFileMapping((HANDLE)INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(int), "TestMem");
  
  
  //将共享内存映射到当前进程地址空间
  
  int* addr = (int*)::MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, sizeof(int));
  
  
  //向共享内存中写数据
  
  *addr = 23;
  
  getchar();
  
  
  //解除共享内存到当前进程地址空间的映射
  
  :: UnmapViewOfFile(addr);
  
  
  //销毁文件映射
  
  ::CloseHandle(hFileMapping);
  
  return 0;
  
  }
  
  
  #include 
  
  #include 
  
  #include 
  
  using namespace std;
  
  
  
  
  int main()
  
  {
  
  //打开一个已命名的文件映射
  
  HANDLE hFileMapping = ::OpenFileMapping(FILE_MAP_READ, false, "TestMem");
  
  
  //将其映射到进程地址空间
  
  int* addr = (int*)::MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, sizeof(int));
  
  
  //读取共享内存中的数据
  
  cout
  getchar();
  
  
  
  //解除到进程地址空间的映射
  
  :: UnmapViewOfFile(addr);
  
  
  //关闭文件映射
  
  ::CloseHandle(hFileMapping);
  
  return 0;
  
  }
  
  2、命名管道
  服务器是唯一一个有权创建命名管道的进程,也只有它才能接受管道客户机的连接请求。
  对一个客户机应用来说,它只能同一个已命名的管道服务器建立连接。
  在客户机和服务器之间,一旦建好连接,两个进程都能对标准的Win32函数,在管道上进行数据的读取与写入。这些函数包括ReadFile和WriteFile等等。
  命名管道的命名格式:   \\ServerName\Pipe\PipeName
  其中ServerName是服务器名字,Pipe固定表示管道,PipeName是管道名称。
  命名管道适用于单机或网络进程间通信。
  服务器端
  
  #include 
  
  #include 
  
  #include 
  
  using namespace std;
  
  
  
  
  int main()
  
  {
  
  //创建一个命名管道
  
  HANDLE hPipe = ::CreateNamedPipe("\\\\.\\pipe\\MyPipe", PIPE_ACCESS_DUPLEX, 0, 2, 0, 0, 0, NULL);
  
  
  //将服务器端连接到命名管道,并监听是否有客户端连接到已创建的命名管道,若有则返回
  
  ::ConnectNamedPipe(hPipe, NULL);
  
  
  //从管道中读数据
  
  char cBuffer[1024] = {0}; 
  
  DWORD dwSize = 0;
  
  ::ReadFile(hPipe, cBuffer, 1024, &dwSize, NULL);
  
  cout
  
  //断开服务器端与命名管道的连接
  
  ::DisconnectNamedPipe(hPipe);
  
  
  //销毁管道
  
  ::CloseHandle(hPipe);
  
  return 0;
  
  }
  
  
  #include 
  
  #include 
  
  #include 
  
  using namespace std;
  
  
  
  
  int main()
  
  {
  
  //客户端等待,直到指定的命名管道可用
  
  ::WaitNamedPipe(L"\\\\.\\pipe\\MyPipe", NMPWAIT_WAIT_FOREVER);
  
  
  //创建一个命名管道的实例
  
  HANDLE hPipe = ::CreateFile(L"\\\\.\\pipe\\MyPipe", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  
  
  //写数据
  
  const char* cWrite = "test pipe";
  
  DWORD dwSize = 0;
  
  ::WriteFile(hPipe, cWrite, (DWORD)strlen(cWrite)+1, &dwSize, NULL);
  
  
  //关闭管道
  
  ::CloseHandle(hPipe);
  
  return 0;
  
  }
  
  3、邮件槽
  邮件槽(Mailslots)提供进程间单向通信能力,服务器端创建邮件槽,客户端通过名字连接邮件槽,同一个邮件槽只允许客户端向服务器端发送数据。
  邮件槽命名与命名管道类似。
  支持单机或不同计算机之间的进程间通信。
  服务器端
  
  #include 
  
  #include 
  
  #include 
  
  using namespace std;
  
  
  
  
  int main()
  
  {
  
  //创建一个邮件槽
  
  //第三个参数若为0,ReadFile即使读不到数据也立刻返回;若为MAILSLOT_WAIT_FOREVER,ReadFile将等待知道读到数据
  
  HANDLE hMail = ::CreateMailslot("\\\\.\\mailslot\\MyMail", 0, MAILSLOT_WAIT_FOREVER, NULL);
  
  
  //从邮件槽中读数据
  
  char cBuffer[1024] = {0}; 
  
  DWORD dwSize = 0;
  
  ::ReadFile(hMail, cBuffer, 1024, &dwSize, NULL);
  
  cout
  
  //销毁邮件槽
  
  ::CloseHandle(hMail);
  
  return 0;
  
  }
  
  
  #include 
  
  #include 
  
  #include 
  
  using namespace std;
  
  
  
  
  int main()
  
  {
  
  //打开一个已命名的邮件槽
  
  //第二个参数必须设为GENERIC_WRITE,因为客户机只能向服务器写入数据。
  
  //第三个参数必须设为FILE_SHARE_READ,允许服务器在邮槽上打开和进行读操作。
  
  HANDLE hMail = ::CreateFile(L"\\\\.\\mailslot\\MyMail", GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  
  
  //写数据
  
  const char* cWrite = "test mail";
  
  DWORD dwSize = 0;
  
  ::WriteFile(hMail, cWrite, (DWORD)strlen(cWrite)+1, &dwSize, NULL);
  
  
  //关闭邮件槽
  
  ::CloseHandle(hMail);
  
  return 0;
  
  }
  
  4、socket连接
  服务器端和客户端通过socket连接通信,适用于网络间进程通信。
  服务器端
  
  #include 
  
  #include 
  
  #pragma comment (lib, "Ws2_32.lib")
  
  
  using namespace std;
  
  
  
  int main()
  
  {
  
  //初始化使用socket函数要用到的dll
  
  WSADATA wd;
  
  ::WSAStartup(MAKEWORD(2,2), &wd);
  
  
  //本机地址信息
  
  sockaddr_in addr;
  
  addr.sin_family            = AF_INET;
  
  addr.sin_port            = htons(1555);
  
  addr.sin_addr.s_addr    = inet_addr("127.0.0.1");
  
  
  //创建套接字,并与本机地址绑定
  
  SOCKET s = ::socket(AF_INET, SOCK_STREAM, 0);
  
  ::bind(s, (const sockaddr*)&addr, sizeof(addr));
  
  
  //监听该套接字,准备接收连接
  
  ::listen(s, 2);
  
  
  //等待客户端连接,若客户端连接则返回,否则一直等待
  
  //返回结果是用来通信的新套接字
  
  sockaddr_in client_addr;
  
  SOCKET ns = ::accept(s, (sockaddr*)&client_addr, NULL);
  
  
  //在新套接字上收数据
  
  while(1)
  
  {
  
  char cBuffer[1024] = {0};
  
  ::recv(ns, cBuffer, 1024, 0);
  
  cout
  }
  
  
  //关闭套接字
  
  ::closesocket(ns);
  
  ::closesocket(s);
  
  
  //ws2.dll的收尾工作
  
  ::WSACleanup();
  
  
  return 0;
  
  }
  
  
  #include 
  
  #include 
  
  #pragma comment (lib, "Ws2_32.lib")
  
  
  using namespace std;
  
  
  
  int main()
  
  {
  
  //初始化使用socket函数要用到的dll
  
  WSADATA wd;
  
  WSAStartup(MAKEWORD(2,2), &wd);
  
  
  //服务器地址信息
  
  sockaddr_in addr;
  
  addr.sin_family            = AF_INET;
  
  addr.sin_port            = htons(1555);
  
  addr.sin_addr.s_addr    = inet_addr("127.0.0.1");
  
  
  //创建套接字,并与服务器连接
  
  SOCKET s = ::socket(AF_INET, SOCK_STREAM, 0);
  
  ::connect(s, (const sockaddr*)&addr, sizeof(addr));
  
  
  //发送数据
  
  while(1)
  
  {
  
  char cData[1024] = {0};
  
  cin>>cData;
  
  ::send(s, cData, (int)strlen(cData)+1, 0);
  
  }
  
  
  //关闭套接字
  
  ::closesocket(s);
  
  
  //ws2.dll的收尾工作
  
  ::WSACleanup();
  
  
  return 0;
  
  }
  
  5、dll共享数据段
  动态链接库被加载后,映射到各自进程地址空间,但位于共享数据段内的变量为所有加载该dll的进程所共享。
  把需要共享的数据变量放入自定义的数据段中, 需要初始化的变量放入   #pragma   data_seg()定义的数据段中;不需初始化的变量放入#pragma   bss_seg()定义的数据段中。
  然后打开/SECTION 开关,请连接器为这些数据段定义共享属性。
  dll文件
  
  //共享数据段
  
  #pragma data_seg("Shared") 
  
  __declspec(dllexport) char g_SharedBuffer[1024] = {0}; 
  
  #pragma data_seg() 
  
  
  #pragma comment(linker, "/Section:Shared,rws")
  
  
  //非共享数据段
  
  __declspec(dllexport) char g_Buffer[1024] = {0}; 
  
  
  #include 
  
  #pragma comment (lib, "..\\..\\dll\\release\\dll")
  
  
  using namespace std;
  
  
  
  int main()
  
  {
  
  //导入dll中的变量
  
  __declspec(dllimport) char g_Buffer[];
  
  __declspec(dllimport) char g_SharedBuffer[];
  
  
  //分别向两个变量中写入数据
  
  strcpy(g_Buffer, "not shared");
  
  strcpy(g_SharedBuffer, "shared");
  
  
  cout
  cout
  
  getchar();
  
  return 0;
  
  }
  
  
  #include 
  
  #pragma comment (lib, "..\\..\\dll\\release\\dll")
  
  
  using namespace std;
  
  
  
  int main()
  
  {
  
  //导入dll中的变量
  
  __declspec(dllimport) char g_Buffer[];
  
  __declspec(dllimport) char g_SharedBuffer[];
  
  
  //输出结果
  
  cout
  cout
  
  getchar();
  
  return 0;
  
  }
  
  6、WM_COPYDATA消息
  发送方只需使用调用SendMessage函数,参数是目的窗口的句柄、传递数据的起始地址、WM_COPYDATA消息。
  接收方只需像处理其它消息那样处理WM_COPY DATA消息,这样收发双方就实现了数据共享。
  7、剪切板
  8、匿名管道
  在父进程和子进程之间,或同一父进程的两个子进程之间传输数据的无名字的单向管道。
  通常由父进程创建管道,然后由要通信的子进程继承通道的读端点句柄或写端点句柄,然后实现通信。
分享到:
评论

相关推荐

    linux进程间通信与同步.pdf

    Linux系统中的进程间通信是典型的虚拟内存系统中的进程间通信:Linux 的进程间通信是不同进程间交换数据的机制。由于Linux系统支持虚拟内 存, 对于每一个进程,系统会为它分配一个单独的进程空间,不同的进程有不同...

    C# 进程间通信 共享内存

    共享内存,顾名思义就是允许两个不相关的进程访问同一个逻辑内存,共享内存是两个正在运行的进程之间共享和传递数据的一种非常有效的方式。...1、进程间通信 2、共享内存 3、托管方式与非托管共享内存

    UNIX网络编程_卷2_进程间通信

    卷2:进程间通信(第2版)》是一部UNIX网络编程的经典之作!进程间通信(IPC)几乎是所有Unix程序性能的关键,理解IPC也是理解如何开发不同主机间网络应用程序的必要条件。《UNIX网络编程.卷2:进程间通信(第2版)》从对...

    进程间通信之信号 sinal ) 完整代码

    进程间通信之信号 sinal ) 唯一的异步通信方式 七种进程间通信方式: 一 无名管道( pipe ) 二 有名管道( fifo ) 三 共享内存 shared memory 四 信号 sinal 五 消息队列 message queue ) 六 信号量 ...

    UNIX网络编程第二卷 进程间通信

    UNIX网络编程第二卷 进程间通信

    C#进程间通信

    操作系统实验之进程间通信(管道方式)。 内涵实验源码及报告文档。 更详尽内容请参考小魏博客:http://blog.csdn.net/xiaowei_cqu/article/details/7041212

    C#使用SendMessage实现进程间通信的方法

    本文实例讲述了C#使用SendMessage实现进程间通信的方法。分享给大家供大家参考。具体分析如下: 为了深入理解消息机制,先来做一个测试项目 在新建项目的Form1的代码中,加入方法: protected override void ...

    Messenger进程间通信

    Messenger进程间通信,包括Service服务端代码和客户端代码;进程内部通信/进程间通信并且应答;

    进程间通信之套接字( socket )——完整代码

    进程间通信之套接字( socket ) 网络间通信 七种进程间通信方式: 一.无名管道( pipe ) 二.有名管道( fifo ) 三.共享内存 ( shared memory ) 四.信号 ( sinal ) 五.消息队列 ( message queue ) 六.信号量 ( ...

    操作系统进程间通信实验

    通过对进程间通信同步/互斥问题的编程实现,加深理解信号量和 P、V 操作的原理; 对 Windows 或 Linux 涉及的几种互斥、同步机制有更进一步的了解;熟悉 Windows 或 Linux 中定义的与互斥、同步有关的函数。

    Linux进程间通信

    Linux进程间通信

    Linux进程间通信.pdf

    Linux进程间通信.pdf Linux进程间通信.pdf

    Linux环境进程间通信(五) 共享内存(上)

    Linux环境进程间通信(五) 共享内存(上)

    Qt进程间通信与同步示例

    Qt进程间通信与同步示例,通过QFile内存映射文件来共享内存达到进程间通信的效果。同时利用QSystemSemaphore 来实现进程同步

    操作系统实验报告(LINUX进程间通信)

    操作系统实验报告(LINUX进程间通信)

    进程间通信的VC++源码实例集,邮槽、匿名管道等

    进程间通信的VC++源码实例集,进程之间的通信以及实现方法实例,通过一些小程序来实现,这些小程序有剪贴板实例、邮槽、匿名管道等,希望对VC++基础用户有帮助。

    利用内存映射文件技术实现进程间通信

    利用内存映射文件技术实现进程间通信,自pudn程序员联合开发网下载

    进程间通信例子

    进程间通信,可以在winform下两个进程,收信息,发信息。很实用的一个例子。

Global site tag (gtag.js) - Google Analytics