vc 进程间通讯

合集下载

c语言进程间通信的几种方法

c语言进程间通信的几种方法

c语言进程间通信的几种方法一、管道(Pipe)管道是一种半双工的通信方式,它可以在两个相关的进程之间传递数据。

具体而言,管道可以分为匿名管道(只能在父子进程之间使用)和有名管道(可以在不相关的进程之间使用)。

1. 匿名管道匿名管道主要通过pipe函数创建,它只能在具有亲缘关系的进程之间使用。

父进程调用pipe函数创建管道后,可以通过fork函数创建子进程,并通过管道进行通信。

父进程通过write函数将数据写入管道,子进程通过read函数从管道中读取数据。

2. 有名管道有名管道是一种特殊的文件,可以在不相关的进程之间进行通信。

创建有名管道可以使用mkfifo函数,在进程间通信时,一个进程以写的方式打开管道,另一个进程以读的方式打开管道,就可以进行数据的读写。

二、共享内存(Shared Memory)共享内存是一种高效的进程间通信方式,它可以在多个进程之间共享同一块物理内存区域。

具体而言,共享内存的创建过程包括创建共享内存区域、映射到进程的虚拟地址空间和访问共享内存。

1. 创建共享内存区域使用shmget函数创建共享内存区域,需要指定共享内存的大小和权限等参数。

2. 映射到进程的虚拟地址空间使用shmat函数将共享内存区域映射到进程的虚拟地址空间,使得进程可以通过访问内存的方式进行通信。

3. 访问共享内存通过对共享内存区域的读写操作,实现进程间的数据交换。

三、消息队列(Message Queue)消息队列是一种可以在不相关的进程之间传递数据的通信方式。

它是一种存放在内核中的消息链表,进程可以通过系统调用对消息进行发送和接收。

1. 创建消息队列使用msgget函数创建消息队列,需要指定消息队列的键值和权限等参数。

2. 发送消息使用msgsnd函数向消息队列中发送消息,需要指定消息队列的标识符和消息的类型等参数。

3. 接收消息使用msgrcv函数从消息队列中接收消息,需要指定消息队列的标识符、接收消息的缓冲区和接收消息的类型等参数。

VC学习笔记之二:进程通信

VC学习笔记之二:进程通信

VC学习笔记之二:进程通信2 进程通信内部进程间通讯和数据交换有消息、共享内存、命名(匿名)管道、邮槽、Windows套接字等多种技术。

我们在今后的课程中将一一介绍。

为了不让其他进程和线程打扰,必需要设置最高的优先级,以下函数设置当前进程和线程到最高的优先级。

SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);2.1 创建进程为了创建进程,需要定义安全属性并且接受一个句柄,可以用此句柄管理进程,比如:改变进程的优先级或者种植进程。

甚至在进程停止运行之后,只要有仍然打开的句柄,进程会继续存在。

为了销毁进程,需要关闭进程的所有句柄。

CreateProcess需要按如下形式调用:BOOL CreateProcess{LPCTSTR lpszImageName,LPCTSTR lpszCmdLine,LPSECURITY_ATTRIBUTES lpsaProcess,LPSECURITY_ATTRIBUTES lpsaThread,BOOL bInheritHandles,DWORD fdwCreate,LPVOID lpvEnvironment,LPTSTR lpszCurrentDir,LPSTARTUPINFO lpStartupInfo,LPPROCESS_INFORMATION lpProcInfo}参数说明:lpszImageName:此参数必须指向可执行文件名(比如,子进程)的字符串,而且不能包含任何命令行参数。

在定位此参数命名文件时,系统不搜索PA TH环境变量定义的目录。

因此程序必须放在当前目录下,或者该字符串必须包含整个路径名。

lpszCmdLine:如果不必传递命令行参数,此参数可以取NULL。

vc socket通信实例总结

vc socket通信实例总结

VC Socket通信实例总结介绍在计算机网络中,Socket是一种用于网络通信的编程接口。

它提供了一种通过网络进行进程间通信的方法,使得不同计算机上的不同进程能够互相发送和接收数据。

VC(Visual C++)是微软公司推出的一款集成开发环境(IDE),它可以用于开发Windows平台下的应用程序。

本文将通过一个实例来展示如何在VC中使用Socket进行网络通信,并总结经验和注意事项。

实例:客户端和服务器端的简单通信环境配置在开始实例之前,我们需要配置好开发环境。

首先,确保电脑上安装了Visual Studio,如果没有安装,可以到微软官方网站下载安装。

其次,我们需要了解一些基本的网络知识,例如IP地址、端口号等。

最后,确保你已经熟悉C++编程语言和Windows编程。

有了这些准备工作,我们就可以开始代码编写了。

服务器端代码首先,我们来编写服务器端的代码。

以下是一个简单的实现,实现了服务器监听端口,并能够接收客户端发送的消息。

```cpp #include #include <winsock2.h>int main() { // 初始化WinSock WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData);// 创建SocketSOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);// 绑定端口sockaddr_in serverAddr;serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(8888); serverAddr.sin_addr.s_addr = INADDR_ANY; bind(serverSocket, (sockaddr*)&serverAddr, sizeof(serverAddr));// 监听端口listen(serverSocket, 10);std::cout << \。

VC_进程间通信

VC_进程间通信
}
//--------------------------------------------------------------------
void CDataSendDlg::OnSendRegmsg()
{????????????????????????????? // 更新数据
void CDataRecvDlg::OnRegReceiveMsg(WPARAM wParam,LPARAM lParam)
{
// 增加用户自定义程序代码

}
其中OnUserReceiveMsg()函数为WM_COMM消息的映射函数,OnRegReceiveMsg()函数为wm_nRegMsg消息的映射函数。可以看出,这两种消息的映射函数形式是一样的。
在接收消息的程序中,除与发送消息的程序需要定义相同的消息外,还需要定义相应的消息映射和消息映射函数,消息的映射方法如下:
ON_MESSAGE(WM_COMM,OnUserReceiveMsg)
ON_REGISTERED_MESSAGE(wm_nRegMsg,OnRegReceiveMsg)
与以上消息映射对应的函数定义如下:
l?????? 间接通信:借助于收发双方进程之外的共享数据结构作为通信中转,如剪贴板。通常接收和发送方的数目可以是任意的。
(3)本地通信和远程通信
l?????? 本地通信方式:这种通信又称之为同机通信,它是在同一台计算机上的程序之间进行的,也就是说客户进程和服务进程位于同一台计算机上。
l?????? 远程通信方式:这种通信又称之为网间的进程通信,要解决的是不同主机进程间的相互通信问题(可把同机进程通信看作是其中的特例)。在这种通信中,首先要解决的是网络间的进程标识问题。同一主机上,不同进程可用进程号(process ID)唯一标识。但在网络环境下,各主机独立分配的进程号不能唯一标识该进程。例如,主机A赋予某个进程号5,在B机中也可以存在5号进程,因此,“5号进程”这句话就没有意义了。其次,操作系统支持的网络协议众多,不同协议的工作方式不同,地址格式也不同。因此,网间的进程通信还要解决多重协议的识别问题。

C语言进程间通信方法

C语言进程间通信方法

C语言进程间通信方法在多道程序设计中,不同的进程之间需要进行通信和协调,以实现数据交换和资源共享。

而在C语言中,有几种主要的进程间通信方法,包括管道、信号、共享内存和消息队列。

下面将逐一介绍这些方法的特点和应用场景。

1. 管道(Pipe)管道是一种半双工的通信方式,它可以在父进程和子进程之间创建一个用于通信的文件描述符。

管道可以分为匿名管道和命名管道两种。

匿名管道只能在具有亲缘关系的进程之间使用,使用函数pipe()可以创建一个管道,并返回两个文件描述符,分别用于读取和写入管道。

父进程可以将数据写入管道,子进程则从管道中读取数据。

命名管道则允许没有亲缘关系的进程之间进行通信,用于创建命名管道的函数为mkfifo()。

不同于匿名管道,命名管道可以在文件系统中创建一个特殊的文件,进程可以通过打开该文件进行通信。

2. 信号(Signal)信号是一种异步的通信方式,它用于通知进程发生了某个特定事件。

在C语言中,可以使用signal()函数来设置信号的处理函数。

进程可以通过发送信号给另一个进程来实现简单的通信。

信号的应用场景较为广泛,例如进程终止和异常处理。

当进程接收到信号时,可以根据信号的类型来执行相应的处理操作。

3. 共享内存(Shared Memory)共享内存允许多个进程之间访问同一块物理内存,以实现高效的数据共享。

进程可以使用shmget()函数创建一个共享内存区域,并使用shmat()函数将共享内存映射到本进程的地址空间中。

共享内存的好处在于数据传输效率高,因为进程直接访问内存而无需通过中介来实现通信。

然而,共享内存的使用需要更加小心,因为没有任何机制来保护共享数据的完整性和一致性。

4. 消息队列(Message Queue)消息队列是一种可以在不同进程之间传输数据的通信方式。

它允许将消息发送到消息队列中,并由其他进程从中读取。

消息的顺序按照发送的顺序进行。

通过调用msgget()函数可以创建或打开一个消息队列,而使用msgsnd()函数和msgrcv()函数分别用于发送和接收消息。

c语言线程间通信和进程间通信方式

c语言线程间通信和进程间通信方式

C语言是一种广泛应用于系统编程和嵌入式开发中的编程语言,它的特点是灵活、高效和强大。

在实际应用中,我们常常需要在不同的线程或进程间进行通信,以实现数据共享和协作处理。

本文将重点介绍C语言中线程间通信和进程间通信的方式,以帮助大家更好地掌握这一重要知识点。

一、线程间通信的方式在C语言中,线程间通信主要有以下几种方式:1. 互斥量互斥量是一种用于保护临界区的同步机制,可以确保在同一时刻只有一个线程访问临界区。

在C语言中,我们可以使用`pthread_mutex_t`类型的变量来创建和操作互斥量。

通过加锁和解锁操作,我们可以实现线程对临界资源的互斥访问,从而避免数据竞争和线程安全问题。

2. 条件变量条件变量是一种用于线程间通信的同步机制,它可以让一个线程等待另一个线程满足特定的条件之后再继续执行。

在C语言中,我们可以使用`pthread_cond_t`类型的变量来创建和操作条件变量。

通过等待和通知操作,我们可以实现线程之间的协调和同步,从而实现有效的线程间通信。

3. 信号量信号量是一种用于控制资源访问的同步机制,它可以限制同时访问某一资源的线程数量。

在C语言中,我们可以使用`sem_t`类型的变量来创建和操作信号量。

通过等待和释放操作,我们可以实现线程对共享资源的争夺和访问控制,从而实现线程间的协作和通信。

二、进程间通信的方式在C语言中,进程间通信主要有以下几种方式:1. 管道管道是一种最基本的进程间通信方式,它可以实现单向的通信。

在C语言中,我们可以使用`pipe`函数来创建匿名管道,通过`fork`和`dup`等系统调用来实现父子进程之间的通信。

管道通常用于在相关进程之间传递数据和实现简单的协作。

2. 共享内存共享内存是一种高效的进程间通信方式,它可以让多个进程共享同一块物理内存空间。

在C语言中,我们可以使用`shmget`、`shmat`等系统调用来创建和操作共享内存,通过对内存的读写操作来实现进程间的数据共享和传递。

《如何使用C语言实现进程间的通信?》

《如何使用C语言实现进程间的通信?》

《如何使用C语言实现进程间的通信?》
C语言来实现进程间的通信有不少方式,具体可以通过以下几
种方式来实现:
1.信号量:使用信号量可以实现同步,通过给进程分配一组允
许的操作许可和它们的数量,用于协调多个进程对共享数据的访问。

信号量可以被用于互斥(当许可只有一个时)或记数(当许可有多个时)。

2.消息传递:根据系统环境,消息传递可以是共享内存,管道,socket等。

消息传递可以帮助多个进程之间实现通信,达到共
同的目的。

3.共享内存:共享内存是指多个进程可以共享同一段内存,进
程之间可以利用该共享内存进行通信。

共享内存需要应用程序有一个全局共享变量,该变量可以在内存中被所有进程访问,从而实现进程间的通信。

4.管道:管道允许进程实现输入和输出数据的一种方式,管道
可以将输入数据从一个进程传递到另一个进程。

C语言可以使
用管道,从而实现进程间的通信,并且不需要使用全局变量来完成此操作。

5.Socket:Socket可以支持多个进程之间的网络通信,从而实
现进程间通信。

Socket可以根据协议实现TCP/IP协议或其他
协议,从而实现进程间通信。

总之,C语言提供了多种实现进程间通信的方式,包括信号量,消息传递,共享内存,管道和socket。

使用C语言可以实现快速,可靠,安全和方便的进程间通信,因此,越来越多的软件开发和应用程序都会选择使用C语言来进行进程间的通信。

c 进程间通信的7种方式,总结出他们的优点

c 进程间通信的7种方式,总结出他们的优点

c 进程间通信的7种方式,总结出他们的优点进程间通信(Inter-process Communication,IPC)是指不同进程之间互相传递数据或者进行通信的一种机制。

在操作系统中,进程是独立运行的程序,拥有自己的内存空间和执行上下文。

为了实现进程之间的协作和数据交换,进程间通信就显得至关重要。

C语言是一种广泛应用于系统开发的编程语言,提供了多种方式进行进程间通信。

下面将介绍C语言中的7种进程间通信方式,并分析它们的优点。

1.管道(Pipe):管道是Unix系统中最早的进程间通信方式之一。

它是一个单向的通道,使用一个文件描述符来表示。

管道需要在进程间建立父子关系,即由一个进程创建出另一个进程,父进程和子进程之间可以通过管道进行通信。

优点:管道简单易用,只需使用read和write等系统调用来实现进程间数据交换。

这种方式适用于有亲缘关系的进程间通信,如父子进程。

2.命名管道(Named Pipe):命名管道是一种特殊的文件,其可以通过文件系统中的路径名来访问。

在进程间通信时,进程可以将数据写入命名管道并从中读取数据。

优点:命名管道可以用于非亲缘关系的进程间通信,进程间不需要有父子关系。

它可以通过文件路径名来访问,更灵活方便。

3.信号量(Semaphore):信号量是一种用于进程同步和互斥的机制,用于解决进程竞争资源的问题。

信号量可以是二进制的(只有0和1),也可以是计数的(可以大于1)。

进程根据信号量的值来决定是否可以继续执行或者访问某个共享资源。

优点:信号量实现了进程之间的互斥和同步,可以防止多个进程同时访问共享资源,从而保证了程序的正确性和数据的一致性。

4.信号(Signal):信号是一种用于进程间通知和中断的机制。

进程可以向另一个进程发送信号,接收到信号的进程可以根据信号的类型来采取相应的行动。

优点:信号可以实现进程间的异步通信,进程可以在任何时候发送信号给其他进程,通过信号处理函数来进行响应。

VC++中进程间相互通信的十一种方法

VC++中进程间相互通信的十一种方法

VC++中进程间相互通信的⼗⼀种⽅法进程通常被定义为⼀个正在运⾏的程序的实例,它由两个部分组成: ⼀个是操作系统⽤来管理进程的内核对象。

内核对象也是系统⽤来存放关于进程的统计信息的地⽅ 另⼀个是地址空间,它包含所有的可执⾏模块或DLL模块的代码和数据。

它还包含动态分配的空间。

如线程堆栈和堆分配空间。

每个进程被赋予它⾃⼰的虚拟地址空间,当进程中的⼀个线程正在运⾏时,该线程可以访问只属于它的进程的内存。

属于其它进程的内存则是隐藏的,并不能被正在运⾏的线程访问。

为了能在两个进程之间进⾏通讯,由以下⼏种⽅法可供参考: 1、剪贴板Clipboard: 在16位时代常使⽤的⽅式,CWnd中提供⽀持 2、窗⼝消息标准的Windows消息以及专⽤的WM_COPYDATA消息 SENDMESSAGE()接收端必须有⼀个窗⼝ 3、使⽤共享内存⽅式(Shared Memory) a.设定⼀块共享内存区域 HANDLE CreateFileMapping(HANDLE,LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD, LPCSTR) 产⽣⼀个file-mapping核⼼对象 LPVOID MapViewOfFile( HANDLE hFileMappingObject, DWORD dwDesiredAcess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, DWORD dwNumberOfBytesToMap ); 得到共享内存的指针 b.找出共享内存 决定这块内存要以点对点(peer to peer)的形式呈现每个进程都必须有相同的能⼒,产⽣共享内存并将它初始化。

每个进程 都应该调⽤CreateFileMapping(),然后调⽤GetLastError().如果传回的错误代码是ERROR_ALREADY_EXISTS,那么进程就可以假设这⼀共享内存区域已经被别的进程打开并初始化了,否则该进程就可以合理的认为⾃⼰排在第⼀位,并接下来将共享内存初始化。

visual c++ ipc 消息队列 应用案例详解

visual c++ ipc 消息队列 应用案例详解

visualc++ipc消息队列应用案例详解一、概述IPC(Inter-ProcessCommunication,进程间通信)是不同进程之间进行信息交换的重要手段。

在C++中,使用消息队列作为IPC的一种方式,可以有效地在不同的进程之间传递数据。

本文将通过一个具体的应用案例,对visualC++中的IPC消息队列进行详解。

二、消息队列的创建与使用1.创建消息队列:在VisualC++中,可以使用`mq_open`函数创建一个消息队列,并指定队列的名称和属性。

例如:`mq_t*msg_queue=mq_open(name,O_CREAT|O_RDWR,0666,attrs);`2.发送消息:使用`mq_send`函数向消息队列发送消息。

例如:`mq_send(msg_queue,msg_ptr,len,0);`3.接收消息:使用`mq_receive`函数从消息队列接收消息。

例如:`msg_ptr=mq_receive(msg_queue);`4.关闭消息队列:使用`mq_close`函数关闭已打开的消息队列。

例如:`mq_close(msg_queue);`三、应用案例以下是一个简单的应用案例,用于演示如何使用IPC消息队列实现不同进程之间的通信。

假设有两个进程:一个是服务器进程,负责接收客户端的请求;另一个是客户端进程,负责向服务器发送请求并接收响应。

1.服务器进程创建消息队列,并监听指定的端口号。

当收到客户端的请求时,将请求信息放入消息队列中。

2.客户端进程通过socket连接到服务器进程,并向其发送连接请求。

当收到连接请求后,服务器进程从消息队列中取出请求信息,并返回响应给客户端进程。

3.客户端进程接收到响应后,将其解析并显示给用户。

四、注意事项1.确保消息队列的名称和属性正确,避免出现重名或无法访问的情况。

2.在发送和接收消息时,要确保数据的完整性和正确性,避免出现数据丢失或损坏的情况。

机器视觉之VC MFC 进程间通信方法总结

机器视觉之VC MFC 进程间通信方法总结

VC/MFC 进程间通信方法总结摘要随着人们对应用程序的要求越来越高,单进程应用在许多场合已不能满足人们的要求。

编写多进程/多线程程序成为现代程序设计的一个重要特点,在多进程程序设计中,进程间的通信是不可避免的。

Microsoft Win32 API提供了多种进程间通信的方法,全面地阐述了这些方法的特点,并加以比较和分析,希望能给读者选择通信方法提供参考。

1 进程与进程通信进程是装入内存并准备执行的程序,每个进程都有私有的虚拟地址空间,由代码、数据以及它可利用的系统资源(如文件、管道等)组成。

多进程/多线程是Windows操作系统的一个基本特征。

Microsoft W in32应用编程接口(Application Programming Interface, API)提供了大量支持应用程序间数据共享和交换的机制,这些机制行使的活动称为进程间通信(InterProcess Communication, IPC),进程通信就是指不同进程间进行数据共享和数据交换。

正因为使用Win32 API进行进程通信方式有多种,如何选择恰当的通信方式就成为应用开发中的一个重要问题,下面本文将对Win32中进程通信的几种方法加以分析和比较。

2 进程通信方法2.1 文件映射文件映射(Memory-Mapped Files)能使进程把文件内容当作进程地址区间一块内存那样来对待。

因此,进程不必使用文件I/O操作,只需简单的指针操作就可读取和修改文件的内容。

Win32 API允许多个进程访问同一文件映射对象,各个进程在它自己的地址空间里接收内存的指针。

通过使用这些指针,不同进程就可以读或修改文件的内容,实现了对文件中数据的共享。

应用程序有三种方法来使多个进程共享一个文件映射对象。

(1)继承:第一个进程建立文件映射对象,它的子进程继承该对象的句柄。

(2)命名文件映射:第一个进程在建立文件映射对象时可以给该对象指定一个名字(可与文件名不同)。

c语言进程间通信的几种方法

c语言进程间通信的几种方法

c语言进程间通信的几种方法进程间通信(Inter-Process Communication,简称IPC)是指在操作系统中,不同进程之间进行信息传递和共享资源的一种机制。

在C语言中,有多种方法可以实现进程间通信,本文将介绍其中的几种常用方法。

1. 管道(Pipe)管道是一种最基本的IPC方法,它可以在父子进程之间传递数据。

在C语言中,可以使用pipe()函数创建一个管道,并使用read()和write()函数进行读写操作。

管道是半双工的,只能实现单向通信,一端写入,另一端读取。

如果需要实现双向通信,可以创建两个管道。

2. 共享内存(Shared Memory)共享内存是一种高效的进程间通信方法,它允许多个进程直接访问同一个内存区域,从而实现数据共享。

在C语言中,可以使用shmget()函数创建共享内存,使用shmat()函数将共享内存映射到进程的地址空间中。

多个进程可以通过读写该共享内存来进行通信。

3. 消息队列(Message Queue)消息队列是一种按照消息的类型进行有序排列的通信方式。

在C语言中,可以使用msgget()函数创建消息队列,使用msgsnd()函数发送消息,使用msgrcv()函数接收消息。

每个消息都有一个类型,接收方可以根据类型来选择接收相应的消息。

4. 信号量(Semaphore)信号量是一种用于进程间同步和互斥的方法。

在C语言中,可以使用semget()函数创建信号量,使用semop()函数对信号量进行操作。

通过对信号量的P操作和V操作,可以实现进程的互斥和同步。

5. 套接字(Socket)套接字是一种用于网络通信的IPC方法,它可以在不同主机之间进行进程间通信。

在C语言中,可以使用socket()函数创建套接字,使用bind()函数绑定地址和端口,使用listen()函数监听连接请求,使用accept()函数接受连接。

通过读写套接字,可以实现进程间的数据传输。

以上是C语言中常用的几种进程间通信方法。

VC中利用内存映射文件实现进程间通信的方法

VC中利用内存映射文件实现进程间通信的方法
s p r i n t f ( b u f , ” He l l o ̄\ ^ n” .
f i l e 。 Wr i t e ( b u f ,s t r l e n ( b u f ) ) ; f i l e . C l o s e ( ) ;
2 . 3 动 态 库 共 享 数 据 段













’ 。…







‘ …
实用第一 智慧密集
… . … . 一 … … . . . … . … . … … … … , .
V C中利用 内存映射文件 实现进程 间通信 的方法
田伟 。余 佥 ,赵神 骅
( 东海舰队参谋部 3 8分队 ,浙江 宁波 3 1 5 0 0 0 )
摘 要 :利 用 内存 映 射 文 件 实现 高 效 的 进 程 间 通 信 , 完成 实 时性 要 求 高 的 X - . 作 、进 程 使 用 内存 映 射 文
件 创 建 环 形 缓 冲 区存 取 数 据 达 到 进 程 间通 信 的 目的 。
关键 词 :Wi n d o w s 系统 ;V C语 言; 内存 映射 文件 ;事件 对象;环形缓 冲区
: : Wr i t e P r o c e s s Me mo r y( h P r o c . I p Me m. b u f ,
b u fs i z e , NUL L ) ;
— —
取 数据 ,一般是在 循环 中读取 、通 常使用 MF C封 装 的
C F i l e 类实现 该功 能 ,永 例代码 如下 :

VisualC 进程间数据通信的实现

VisualC  进程间数据通信的实现

Visual C++进程间数据通信的实现2006-01-19 08:43作者:刘涛出处:天极开发责任编辑:方舟在Windows系统中,各个应用程序(进程)之间常常需要交换、传递数据,这就要解决进程间的数据通信问题。

在最初的16位Windows3.x系统中,所有Windows应用程序共享单一地址,任何进程都能够对这一共享地址空间的数据进行读写操作。

随着Windwos98、WindowsNT、Windows2000等32位的操作系统的出现,规定每个进程都有自己的地址空间,一个Windows进程不能存取另一个进程的私有数据,也就是说,虽然两个进程可以用具有相同值的指针寻址,但所读写的只是它们各自的数据,这样就减少了进程之间的相互干扰。

那么上述技术的采用是否意味着各个应用程序之间不能进行数据交换了呢?答案当然是否定的,强大的Windows系统早已为我们设计了很多方案来解决进行间的通信问题,这里我们只探讨如何通过动态数据交换(DDE)方法实现进程间的数据通信。

本实例程序功能如下,服务器端有两个数据项,一个是输入的字符串,另一个是定时增加的整数。

运行该程序的两个实例后,两个程序就可以建立DDE连接,实现数据的传递,并将另外一个实例传送过来的数据显示出来。

下图为程序编译运行后的效果图:图一、DDE方法实现进程间数据通信程序的界面效果图一、实现方法自从微软推出Windows操作系统以来,动态数据交换(DDE)就已经成为Windows的部分,并且很多Windwos应用程序都使用了DDE技术来实现进程之间的数据交换。

DDE是建立在Windows内部消息系统、全局和共享全局内存基础上的一种协议,用来协调Windows应用程序之间的数据交换和命令调用,它已经成为应用程序之间通信的一种常用方法。

DDE应用程序可以分为四种类型:客户类型、服务器类型、客户/服务器类型和监视器。

DDE会话发生在客户应用程序和服务器应用程序之间。

VC++之线程和进程之用命名管道实现进程间通信

VC++之线程和进程之用命名管道实现进程间通信

一、创建应用工程1、创建单文档应用工程2、添加新单文档应用工程二、编辑菜单项1、编辑Thread工程之菜单项2、编辑Child工程之菜单项三、添加变量、函数1、添加变量a、为CThreadView类添加变量b、为CChildView类添加变量2、添加函数a、为CThreadView类添加菜单消息响应函数b、为CChildView类添加菜单消息响应函数四、添加代码1、为CThreadView类添加代码a、添加初始化代码CThreadView::CThreadView(){// TODO: add construction code herepipe=NULL;}CThreadView::~CThreadView(){if(pipe)CloseHandle(pipe);}b、添加消息响应函数代码void CThreadView::OnPipeCreate(){// TODO: Add your command handler code herepipe=CreateNamedPipe("\\\\.\\pipe\\mypipe",PIPE_ACCESS_DUPLEX|FILE_F LAG_OVERLAPPED,0,1,1024,1024,0,NULL);if(INVALID_HANDLE_VALUE==pipe){MessageBox("管道创建失败");pipe=NULL;return;}HANDLE event;event=CreateEvent(NULL,TRUE,FALSE,NULL);if(!event){MessageBox("事件对象创建失败");CloseHandle(pipe);pipe=NULL;return;}OVERLAPPED overlap;ZeroMemory(&overlap,sizeof(OVERLAPPED));overlap.hEvent=event;ConnectNamedPipe(pipe,&overlap);//等待客户端连接WaitForSingleObject(event,INFINITE);}void CThreadView::OnPipeRead(){// TODO: Add your command handler code herechar readbuf[100];DWORD dwread;ReadFile(pipe,readbuf,100,&dwread,NULL);MessageBox(readbuf);}void CThreadView::OnPipeWrite(){// TODO: Add your command handler code herechar buf[]="你好,长江!";DWORD dwwrite;WriteFile(pipe,buf,strlen(buf)+1,&dwwrite,NULL);}2、为CChildView类添加代码a、添加初始化代码CChildView::CChildView(){// TODO: add construction code herepipe=NULL;}CChildView::~CChildView(){if(pipe)CloseHandle(pipe);}b、添加消息响应函数代码void CChildView::OnConnect(){// TODO: Add your command handler code hereWaitNamedPipe("\\\\.\\pipe\\mypipe",NMPWAIT_WAIT_FOREVER);pipe=CreateFile"\\\\.\\pipe\\mypipe",GENERIC_READ|GENERIC_WRITE,0,NU LL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);}void CChildView::OnRead(){// TODO: Add your command handler code herechar readbuf[100];DWORD dwread;ReadFile(pipe,readbuf,100,&dwread,NULL);MessageBox(readbuf);}void CChildView::OnWrite(){// TODO: Add your command handler code herechar buf[]="你好,黄河!";DWORD dwwrite;WriteFile(pipe,buf,strlen(buf)+1,&dwwrite,NULL);}五、编译六、运行七、函数说明1、CreateNamedPipe()函数声明HANDLE CreateNamedPipe(LPCTSTR lpName,DWORD dwOpenmode,DWORD dwPi peMode,DWPRD mMaxInstances,DWORD nOutBufferSize,DWORD nInbufferSiz e,DWORD nDefaultTimeOut,LPSECURITY_ATTRIBUTES lpSecurityAttributes)功能:创建一命名管道实例。

C语言进程和进程之间通讯的方式_管道的使用

C语言进程和进程之间通讯的方式_管道的使用

C语⾔进程和进程之间通讯的⽅式_管道的使⽤进程和进程之间的内存是相对独⽴的进程和进程通讯原理进程和进程之间通讯的⽅式管道(使⽤最简单)只能⽤在有⾎缘关系的进程之中信号(开销最⼩)共享映射区(⽆⾎缘关系)本地套接字(最稳定,实现复杂度最⾼)管道管道必须⽤在有⽗⼦关系的进程中管道是⼀种最基本的IPC机制,作⽤与有⾎缘关系的进程之间,调⽤pipe系统函数,即可以创建⼀个管道,其本质是⼀个伪⽂件(实为内核缓存区)由两个⽂件描述符引⽤,⼀个表⽰读端,⼀个表⽰写端规定数据从管道的写⼊端流⼊管道,从读取端读出局限性:⾃⼰写,不能⾃⼰读数据不可以反复读单⼯通信⾎缘关系进程间可⽤pipe函数,创建并打开管道int pipe (int fd[2]);// 参数// fd[0] : 读端// fd[1] : 写端例:#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <pthread.h>void sys_err(const char *str){perror(str);exit(1);}int main(int agrc, char *argv[]){int ret;int fd[2];pid_t pid;char buf[1024];ret = pipe(fd);if (ret == -1){sys_err("pipe error");}pid = fork();if (pid>0){close(fd[0]); // 关闭读端write(fd[1], "hello pipe", strlen("hello pipe")); close(fd[1]);// ⽗进程} else if(pid==0){// ⼦进程close(fd[1]);ret = read(fd[0], buf, size(buf));write(STDOUT_FILENO, buf, ret);close(fd[0]);}return 0;}管道的读写⾏为读管道管道有数据,read返回实际读到的字节数管道⽆数据,⽆写端,read返回0有些端,read堵塞等待写管道⽆读端,异常终⽌有读端,管道已满,阻塞等待管道未满,返回写出的字节个数。

CC++进程间通信内存共享

CC++进程间通信内存共享

CC++进程间通信内存共享介绍内存共享前,说下之前的误区,觉得,可以⽤指针来在⽗⼦进程中传递数据,其实,在fork()后,⽗⼦进程的地址空间是相互独⽴的!所以在⽗⼦进程间传递指针是没有意义的。

这⾥就涉及到物理地址和逻辑地址(或称虚拟地址)的概念。

从逻辑地址到物理地址的映射称为地址重定向。

分为:静态重定向--在程序装⼊主存时已经完成了逻辑地址到物理地址和变换,在程序执⾏期间不会再发⽣改变。

动态重定向--程序执⾏期间完成,其实现依赖于硬件地址变换机构,如基址寄存器。

逻辑地址:CPU所⽣成的地址。

CPU产⽣的逻辑地址被分为 :p (页号)它包含每个页在物理内存中的基址,⽤来作为页表的索引;d (页偏移),同基址相结合,⽤来确定送⼊内存设备的物理内存地址。

物理地址:内存单元所看到的地址。

⽤户程序看不见真正的物理地址。

⽤户只⽣成逻辑地址,且认为进程的地址空间为0到max。

物理地址范围从R+0到R+max,R为基地址,地址映射-将程序地址空间中使⽤的逻辑地址变换成内存中的物理地址的过程。

由内存管理单元(MMU)来完成。

fork()会产⽣⼀个和⽗进程完全相同的⼦进程,但⼦进程在此后多会exec系统调⽤,出于效率考虑,linux中引⼊了“写时复制“技术,也就是只有进程空间的各段的内容要发⽣变化时,才会将⽗进程的内容复制⼀份给⼦进程。

在fork之后exec之前两个进程⽤的是相同的物理空间(内存区),⼦进程的代码段、数据段、堆栈都是指向⽗进程的物理空间,也就是说,两者的虚拟空间不同,但其对应的物理空间是同⼀个。

当⽗⼦进程中有更改相应段的⾏为发⽣时,再为⼦进程相应的段分配物理空间,如果不是因为exec,内核会给⼦进程的数据段、堆栈段分配相应的物理空间(⾄此两者有各⾃的进程空间,互不影响),⽽代码段继续共享⽗进程的物理空间(两者的代码完全相同)。

⽽如果是因为exec,由于两者执⾏的代码不同,⼦进程的代码段也会分配单独的物理空间。

C和C#进程之间通过命名管道通信(精)

C和C#进程之间通过命名管道通信(精)

C++和C#进程之间通过命名管道通信“命名管道”是一种简单的进程间通信(IPC)机制。

命名管道可在同一台计算机的不同进程之间,或在跨越一个网络的不同计算机的不同进程之间,支持可靠的、单向或双向的数据通信。

用命名管道来设计应用程序实际非常简单,并不需要事先深入掌握基层网络传送协议(如TCP/IP或IPX)的知识。

因为命名管道利用了微软网络提供者(MSNP)重定向器,通过一个网络,在各进程间建立通信。

这样一来,应用程序便不必关心网络协议的细节。

命令管道是围绕Windows文件系统设计的一种机制,采用“命名管道文件系统”(NamedPipeFileSystem,NPFS)接口。

因此,客户机和服务器应用可利用标准的Win32文件系统API函数(如ReadFile和WriteFile)来进行数据的收发。

通过这些API函数,应用程序便可直接利用Win32文件系统命名规范,以及WindowsNT/Windows2000文件系统的安全机制。

NPFS依赖于MSNP重定向器在网上进行命名管道数据的发送和接收。

这样一来,便可实现接口的“与协议无关”特性:若在自己开发的应用程序中使用命名管道在网上不同的进程间建立通信,程序员不必关心基层网络传送协议(如TCP和IPX等等)的细节。

客户机和服务器命名管道最大的特点便是建立一个简单的客户机/服务器程序设计体系。

在这个体系结构中,在客户机与服务器之间,数据既可单向传递,亦可双向流动。

对命名管道服务器和客户机来说,两者的区别在于:服务器是唯一一个有权创建命名管道的进程,也只有它才能接受管道客户机的连接请求。

对一个客户机应用来说,它只能同一个现成的命名管道服务器建立连接。

在客户机应用和服务器应用之间,一旦建好连接,两个进程都能对标准的Win32函数,在管道上进行数据的读取与写入。

这些函数包括ReadFile和WriteFile等等。

服务器要想实现一个命名管道服务器,要求必须开发一个应用程序,通过它创建命名管道的一个或多个“实例”,再由客户机进行访问。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

好了我们下面来写两个进程来实现它们的通信, 事先说明我写的只是关键代码并不能直接运行
发送方:
void Send(char* pSnd)
{
if (OpenClipboard())
{
HANDLE hClip;
if (!CreatePipe(&m_hRead, &m_hWrite, &sa, 0)
{
return;
}
STARTUPINFO sui;
PROCESS_INFOMATION pi; // 保存了所创建子进程的信息
BOOL CreatePipe(PHANDLE hReadPipe, PHANDLE hWritePipe, LPSECURITY_ATTRIBUTES lpPipeAttributes, DWORD nSize)
这个API函数是有用来创建匿名管道的,它返回管道的读写句柄(hReadPipe,hWritePipe), 记住lpPipeAttributes不能为NULL,因为这意味着函数的返回句柄不能被子进程所继承,你要知道匿名管道可是实现父子进程通信的阿,只有当一个子进程从其父进程中继承了匿名管道句柄后,这两个进程才可以通信,lpPipeAttributes不为NULL还远不够,LPSECURITY_ATTRIBUTES这个结构体的内容去查MSDN吧,我只告诉你其中的BOOL bInheritHandle这个成员变量要赋值为TRUE, 这样才真正实现了子进程可以从父进程中继承匿名管道.
2. 匿名管道(Pipe)
现在大多数都是基于管道通信的,因为每两个进程都可以共享一个管道来进行单独的对话,就象打电话单独占用一条线路一样,而不必担心像剪贴板一样会有串音, 匿名管道是一种只能在本地机器上实现两个进程间通信的管道,它只能用来实现一个父进程和一个子进程之间实现数据传输.其实它是非常有用的,我做过一个实际的项目就是利用匿名管道,项目就是让我写一个Ping程序来监测网络的通信状况,并且要把统计结果和执行过程显示在我们的软件里, windows有一个自带的ping程序,而且有执行过程和统计,所以我没必要再发明一个(重复发明就等于犯罪----程序员要牢记阿), 只是windows的那个Ping程序的执行结果都显示在了CMD的界面上了,我需要把它提取出来显示在我们的软件界面上,于是我就利用了匿名管道实现了这个程序, 当我们的软件要启动Ping任务时,我就先CreatePipe创建匿名管道,再CreateProcess启动了windows下面的Ping程序(它作为我们软件的子进程),当然要把管道的读写句柄一起传给子进程,这样我就可以轻松的把Ping的执行结果了写入到我的Buffer里了,是不是很easy。
BOOL IsClipboardFormatAvailable(UINT uFormat)
这个函数的作用就是要检查一下剪贴板中的数据是否是uFormat形式的,比如我现打开了mspaint(画图板)程序画了几笔,然后Ctrl+C,再打开notepad程序Ctrl+V,你当然知道这不会成功,它就是使用了这个API函数在粘贴前判断了一下剪贴板中的数据类型是否是我所需要的.
上面这段程序就相当于你执行了Ctrl+V操作,它把剪贴板中的数据取了出来;
剪贴板是系统提供的,所有进程都可以访问它,它就是一段全局内存区,操作系统中的每个进程就都会像线程访问共享变量一样的使用它,很简单,但是问题很多,正是因为所有的进程都可以访问它,所以如果你的两个进程间的通信如果使用这种方式的话,第一,通信效率不高;第二,会影响到其他进程的执行, 如果我现在Ctrl+C了一段文字,再执行Ctrl+V的时候却出现了一些乱七八糟的东西的话那就会很麻烦, 所以可以基于剪贴板来做一个简单的病毒程序,如果你有兴趣的话;
{
....
private:
HANDLE m_hWrite;
HANDLE m_hRead;
}
void CParent::onCreatePipe()
{
SECURITY_ATTRIBUTES sa; // 父进程传递给子进程的一些信息
1. 剪贴板(clipboaቤተ መጻሕፍቲ ባይዱd)
其实这个东西我们每天操作电脑的时候都在接触,我们经常实用ctrl+c和ctrl+v就是基于了剪贴板的方式来实现了两个进程间的通信, 就拿我现在来说吧,我在写这篇文章的时候是在notepad下写的, 一会我要把这篇文章里的所有文字都粘贴到csdn的网页上, 这里就是两个进程,一个是notepad进程和一个IE进程进行通信, 它们要传输的数据格式是TEXT,当然你也可以把这些内容拷贝到word、Excel、PowerPoint甚至是另一个notepad上面(你要清楚再启动一个notepad,这个跟前一个notepad是两个进程,虽然它们长得很像),这就说明剪贴板是所有程序都可以访问的,如果你对多线程编程比较了解的话, 你就会明白一个数据一旦要被很多线程访问,如果这些线程中有一些需要求改这个数据,就要对这个数据加锁来保证数据的正确性了,剪贴板也是一样的,当我把这段文字ctrl+c时,它就要先对系统中的剪贴板加锁,然后把内容放进去,再释放锁,如果你明白了以上的一些道理,那么请你继续往下看,如果还没太明白那也请你继续往下看, 也许你对文字的理解能力已经落后于对代码的理解了.
pBuf = (char *)GlobalLock(hClip); // 得到句柄标识的内存的实际物理地址,lock后系统就不能把它乱移动了
strcpy(pBuf, pSnd);
GlobalUnloak(hClip); // 跟open和close的关系是一样的,有lock的也不要忘记unlock
ZeroMemory(&sui, sizeof(STARTUPINFO)); // 对一个内存区清零,最好用ZeroMemory, 它的速度要快于memset
sui.cb = sizeof(STARTUPINFO);
sui.dwFlags = STARTF_USESTDHANDLES;
HANDLE hClip;
char *pBuf = NULL;
hClip = GetClipboardData(CF_TEXT); // 根据编程中的对称原则,这个我就不介绍了
pBuf = (char *)GlobalLock(hClip);
SetClipboardData(CF_TEXT, hClip);
CloseClipboard(); // 有open就不要忘记close
}
}
在你的程序中加入以上这段话,它就把pSnd中的内容发到了剪贴板上,相当于你作了Ctrl+C, 不信你可以执行这段程序后,打开一个notepad然后手动Ctrl+v看看是不是很惊奇.
GlobalUnlock(hClip);
MessageBox(pBuf); //显示出来
}
&nb
sp; CloseClipboard();
}
}
void Receive()
{
if (OpenClipboard())
{
if (IsClipboardFormatAvailable(CF_TEXT))//判断剪贴板中的数据是否是文本
{
BOOL OpenClipboard()
windows提供的一个API函数,作用是打开剪贴板,如果程序打开了剪贴板,则其他程序经不能修改剪贴板(道理上面讲了),直到CloseClipboard(), 在windows中所有带有Open这个单词的函数都会有一个与之对应的带有Close这个单词的函数, 而且你在open之后一定不要忘记close,你可以自己试试看,只调用OpenClipboard()而不去执行CloseClipboard()会有什么效果,至今我还没有发现例外的情况,如果你发现了请你告诉我.
BOOL CreateProcess(...)
这个系统API函数是用来在你的进程中启动一个子进程用的,它的参数实在太多了,你还是去查MSDN吧,别怪我太懒惰,我只说几个关键的地方,不想说的太详细.
下面我就在写一个程序利用匿名管道来通信
父进程的实现:
Class CParent
在Windows下各个任务是以不同的进程来完成的,当一个进程启动后,操作系统为其分配了4GB的私有地址空间,由于位于同一个进程中的线程共享同一个地址空间,所以线程间的通信很简单,就像两个人如果在同一个房间里说话的话就比较容易,只要动动嘴皮子就OK了, 但是如果在两个国家里就比较麻烦,必须借助于一些其他的手段,比如打电话等. 以下介绍四种进程通信方式,虽然是在windows下的环境但是在其他的操作系统里也遵循着同样的原理,不信的话可以把大学里的操作系统教材拿出来看看, 它们分别是剪贴板、 匿名管道、命名管道和邮槽。
sa.bInheritHandle = TRUE; // 还记得我上面的提醒吧,这个来允许子进程继承父进程的管道句柄
sa.lpSecurityDescriptor = NULL;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
char *pBuf = NULL; // 对一个指针变量以NULL来初始化是个很好的习惯
EmptyClipboard(); // 清空剪贴板上的内容
hClip = GlobalAlloc(GMEM_MOVEABLE, strlen(pSnd) + 1);
HANDLE SetClipboardData(UINT uFormat, HANDLE hMem)
它的作用是将hMem所“代表”的内存中的内容以uFormat的格式放到剪贴板上,详细的参数说明去查MSDN吧,这里你可能有一些疑问,hMem是个句柄而内存是用指针来访问的,你说的没错,所以我用了“代表”这个词而没有用“指向”,在windows里很多资源都会有一个HANDLE以它来标识各个资源一遍于操作系统的管理,内存也一样,我们一般动态开辟(用new, malloc)的heap都不会被操作系统任意移动,因为它是一个进程的私有空间,而如果你开辟全局Heap数据的话,操作系统很可能会移动它,如果这个时候你已然使用指针的话,那么操作系统一旦移动了一块全局Heap数据就要修改到所有指向这块内存的指针,这显然不现实,而这个时候如果你已然使用你的指针来管理那块内存的话,那就出了大麻烦,因为那块内存已经被移走了,而如果使用句柄来标识这块内存的话则会解决这个问题,因为它只是一个标签,并没有实际的物理意义,就像如果你使用一个人的家庭住址来标识这个人的话就会有麻烦,因为一旦他搬走了,你就找错人了, 但是以身份证号就OK了, 详细的情况可以参考GlobalAlloc这个函数。
相关文档
最新文档