项目中需要将C++代码计算出的参数传递给C#代码做后续处理,就需要跨语言通信。

由于命名管道可以跨语言,跨平台,跨线程通信,实际上命名管道不仅可在同一台计算机的不同进程之间传输数据,甚至能在跨越一个网络的不同计算机的不同进程之间,支持可靠的、单向或双向的数据通信。

C#端:命名管道的API都封装在类PipeNative中,在使用时,直接调用类中的函数即可。

类PipeNative:

/****************************** Module Header ******************************\
* Module Name:  PipeNative.cs
* Project:      CSNamedPipeClient
* Copyright (c) Microsoft Corporation.
*
* The P/Invoke signatures of some native Named Pipe APIs.
*
* This source is subject to the Microsoft Public License.
* See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
* All other rights reserved.
*
* History:
* * 1/27/2009 9:21 PM Jialiang Ge Created
\***************************************************************************/using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Security;/// <summary>
/// Desired Access of File/Device
/// </summary>
[Flags]
public enum FileDesiredAccess : uint
{GENERIC_READ = 0x80000000,GENERIC_WRITE = 0x40000000,GENERIC_EXECUTE = 0x20000000,GENERIC_ALL = 0x10000000
}/// <summary>
/// File share mode
/// </summary>
[Flags]
public enum FileShareMode : uint
{Zero = 0x00000000,                  // No sharing.FILE_SHARE_DELETE = 0x00000004,FILE_SHARE_READ = 0x00000001,FILE_SHARE_WRITE = 0x00000002
}/// <summary>
/// File Creation Disposition
/// </summary>
[Flags]
public enum FileCreationDisposition : uint
{CREATE_NEW = 1,CREATE_ALWAYS = 2,OPEN_EXISTING = 3,OPEN_ALWAYS = 4,TRUNCATE_EXISTING = 5
}/// <summary>
/// Named Pipe Open Modes
/// http://msdn.microsoft.com/en-us/library/aa365596.aspx
/// </summary>
[Flags]
public enum PipeOpenMode : uint
{PIPE_ACCESS_INBOUND = 0x00000001,   // Inbound pipe access.PIPE_ACCESS_OUTBOUND = 0x00000002,  // Outbound pipe access.PIPE_ACCESS_DUPLEX = 0x00000003     // Duplex pipe access.
}/// <summary>
/// Named Pipe Type, Read, and Wait Modes
/// http://msdn.microsoft.com/en-us/library/aa365605.aspx
/// </summary>
public enum PipeMode : uint
{// Type ModePIPE_TYPE_BYTE = 0x00000000,        // Byte pipe type.PIPE_TYPE_MESSAGE = 0x00000004,     // Message pipe type.// Read ModePIPE_READMODE_BYTE = 0x00000000,    // Read mode of type Byte.PIPE_READMODE_MESSAGE = 0x00000002, // Read mode of type Message.// Wait ModePIPE_WAIT = 0x00000000,             // Pipe blocking mode.PIPE_NOWAIT = 0x00000001            // Pipe non-blocking mode.
}/// <summary>
/// The class exposes kernel32.dll methods for named pipes communication.
/// </summary>
[SuppressUnmanagedCodeSecurity]
public class PipeNative
{/// <summary>/// Unlimited server pipe instances./// </summary>public const uint PIPE_UNLIMITED_INSTANCES = 255;/// <summary>/// The operation completed successfully./// </summary>public const ulong ERROR_SUCCESS = 0;/// <summary>/// The system cannot find the file specified./// </summary>public const ulong ERROR_CANNOT_CONNECT_TO_PIPE = 2;/// <summary>/// All pipe instances are busy./// </summary>public const ulong ERROR_PIPE_BUSY = 231;/// <summary>/// The pipe is being closed./// </summary>public const ulong ERROR_NO_DATA = 232;/// <summary>/// No process is on the other end of the pipe./// </summary>public const ulong ERROR_PIPE_NOT_CONNECTED = 233;/// <summary>/// More data is available./// </summary>public const ulong ERROR_MORE_DATA = 234;/// <summary>/// There is a process on other end of the pipe./// </summary>public const ulong ERROR_PIPE_CONNECTED = 535;/// <summary>/// Waiting for a process to open the other end of the pipe./// </summary>public const ulong ERROR_PIPE_LISTENING = 536;/// <summary>/// Waits indefinitely when connecting to a pipe./// </summary>public const uint NMPWAIT_WAIT_FOREVER = 0xffffffff;/// <summary>/// Does not wait for the named pipe./// </summary>public const uint NMPWAIT_NOWAIT = 0x00000001;/// <summary>/// Uses the default time-out specified in a call to the /// CreateNamedPipe method./// </summary>public const uint NMPWAIT_USE_DEFAULT_WAIT = 0x00000000;/// <summary>/// Invalid operating system handle./// </summary>public const int INVALID_HANDLE_VALUE = -1;/// <summary>/// Retrieves the calling thread's last-error code value./// </summary>/// <returns>The return value is the calling thread's last-error /// code value.</returns>[DllImport("kernel32.dll", SetLastError = true)]  //设置SetLastError = true,表示可利用GetLastError获取上一次函数运行时反返回的错误public static extern uint GetLastError();  //〖2〗-系统找不到指定的文件。/// <summary>/// Creates an instance of a named pipe and returns a handle for /// subsequent pipe operations./// </summary>/// <param name="lpName">Pipe name</param>/// <param name="dwOpenMode">Pipe open mode</param>/// <param name="dwPipeMode">Pipe-specific modes</param>/// <param name="nMaxInstances">Maximum number of instances</param>/// <param name="nOutBufferSize">Output buffer size</param>/// <param name="nInBufferSize">Input buffer size</param>/// <param name="nDefaultTimeOut">Time-out interval</param>/// <param name="pipeSecurityAttributes">Security attributes</param>/// <returns>If the function succeeds, the return value is a handle /// to the server end of a named pipe instance.</returns>[DllImport("kernel32.dll", SetLastError = true)]public static extern IntPtr CreateNamedPipe(String lpName,                      // Pipe namePipeOpenMode dwOpenMode,            // Pipe open modePipeMode dwPipeMode,                // Pipe-specific modesuint nMaxInstances,                 // Maximum number of instancesuint nOutBufferSize,                // Output buffer sizeuint nInBufferSize,                 // Input buffer sizeuint nDefaultTimeOut,               // Time-out intervalIntPtr pipeSecurityAttributes       // Security Attributes);/// <summary>/// Enables a named pipe server process to wait for a client /// process to connect to an instance of a named pipe./// </summary>/// <param name="hHandle">Handle to the server end of a named pipe /// instance.</param>/// <param name="lpOverlapped">Pointer to an Overlapped object./// </param>/// <returns>If the function succeeds, the return value is nonzero./// </returns>[DllImport("kernel32.dll", SetLastError = true)]public static extern bool ConnectNamedPipe(IntPtr hHandle,                     // Handle to named pipeIntPtr lpOverlapped                 // Overlapped structure);/// <summary>/// Waits until either a time-out interval elapses or an instance /// of the specified named pipe is available for connection./// </summary>/// <param name="name">Pointer to a null-terminated string that  /// specifies the name of the named pipe.</param>/// <param name="timeout">Number of milliseconds that the function  /// willwait for an instance of the named pipe to be available./// </param>/// <returns>If an instance of the pipe is available before the /// time-out interval elapses, the return value is nonzero.</param>[DllImport("kernel32.dll", SetLastError = true)]public static extern bool WaitNamedPipe(String name,int timeout);/// <summary>/// Sets the read mode and the blocking mode of the specified named pipe./// </summary>/// <remarks>/// If the specified handle is to the client end of a named pipe and if/// the named pipe server process is on a remote computer, the function/// can also be used to control local buffering./// </remarks>/// <param name="hHandle">Handle to the named pipe instance.</param>/// <param name="lpMode">Pointer to a variable that supplies the new mode./// </param>/// <param name="lpMaxCollectionCount">Pointer to a variable that /// specifies the maximum number of bytes collected on the client computer/// before transmission to the server.</param>/// <param name="lpCollectDataTimeout">Pointer to a variable that /// specifies the maximum time, in milliseconds, that can pass before/// a remote named pipe transfers information over the network.</param>/// <returns>If the function succeeds, the return value is nonzero./// </returns>[DllImport("kernel32.dll", SetLastError = true)]public static extern bool SetNamedPipeHandleState(IntPtr hHandle,ref PipeMode lpMode,IntPtr lpMaxCollectionCount,IntPtr lpCollectDataTimeout);/// <summary>/// Creates or opens a file, directory, physical disk, volume, console/// buffer, tape drive, communications resource, mailslot, or named /// pipe./// </summary>/// <param name="lpFileName">File name.</param>/// <param name="dwDesiredAccess">Access to the object (reading, /// writing, or both).</param>/// <param name="dwShareMode">Sharing mode of the object (reading, /// writing, both, or neither).</param>/// <param name="fileSecurityAttributes">Pointer to a /// SecurityAttributes object that determines whether the returned /// handle can be inherited by child processes.</param>/// <param name="dwCreationDisposition">Action to take on files that /// exist, and which action to take when files do not exist</param>/// <param name="dwFlagsAndAttributes">File attributes and flags./// </param>/// <param name="hTemplateFile">Handle to a template file.</param>/// <returns>If the function succeeds, the return value is an open /// handle to the specified file.</returns>[DllImport("kernel32.dll", SetLastError = true)]public static extern IntPtr CreateFile(String lpFileName,                  // File name 文件名FileDesiredAccess dwDesiredAccess,  // Access mode 通道模式FileShareMode dwShareMode,          // Share mode 共享模式IntPtr fileSecurityAttributes,      // Security Attributes 安全属性FileCreationDisposition dwCreationDisposition,// How to createuint dwFlagsAndAttributes,          // File attributes 文件属性uint hTemplateFile);                // Handle to template file/// <summary>/// Reads data from a file, starting at the position indicated by the /// file pointer./// </summary>/// <param name="hHandle">Handle to the file to be read.</param>/// <param name="lpBuffer">Pointer to the buffer that receives the /// data read from the file.</param>/// <param name="nNumberOfBytesToRead">Number of bytes to be read from/// the file.</param>/// <param name="lpNumberOfBytesRead">Pointer to the variable that /// receives the number of bytes read.</param>/// <param name="lpOverlapped">Pointer to an Overlapped object.</param> /// <returns>The ReadFile function returns when one of the following /// conditions is met: a write operation completes on the write end /// of the pipe, the number of bytes requested has been read, or an/// error occurs.</returns>[DllImport("kernel32.dll", SetLastError = true)]public static extern bool ReadFile(IntPtr hHandle,                     // Handle to filebyte[] lpBuffer,                    // Data bufferuint nNumberOfBytesToRead,          // Number of bytes to readout uint lpNumberOfBytesRead,       // Number of bytes readIntPtr lpOverlapped                 // Overlapped buffer);/// <summary>/// Writes data to a file at the position specified by the file pointer./// </summary>/// <param name="hHandle">Handle to the file.</param>/// <param name="lpBuffer">Pointer to the buffer containing the data to /// be written to the file.</param>/// <param name="nNumberOfBytesToWrite">Number of bytes to be write to /// the file.</param>/// <param name="lpNumberOfBytesWritten">Pointer to the variable that/// receives the number of bytes written.</param>/// <param name="lpOverlapped">Pointer to an Overlapped object./// </param>/// <returns>If the function succeeds, the return value is nonzero./// </returns>[DllImport("kernel32.dll", SetLastError = true)]public static extern bool WriteFile(IntPtr hHandle,                     // Handle to filebyte[] lpBuffer,                    // Data bufferuint nNumberOfBytesToWrite,         // Number of bytes to writeout uint lpNumberOfBytesWritten,    // number of bytes writtenIntPtr lpOverlapped                 // Overlapped buffer);/// <summary>/// Closes an open object handle./// </summary>/// <param name="hHandle">Handle to an open object.</param>/// <returns>If the function succeeds, the return value is nonzero./// </returns>[DllImport("kernel32.dll", SetLastError = true)]public static extern bool CloseHandle(IntPtr hHandle);/// <summary>/// Flushes the buffers of the specified file and causes all buffered/// data to be written to the file./// </summary>/// <param name="hHandle">Handle to an open file.</param>/// <returns>If the function succeeds, the return value is nonzero./// </returns>[DllImport("kernel32.dll", SetLastError = true)]public static extern bool FlushFileBuffers(IntPtr hHandle);/// <summary>/// Disconnects the server end of a named pipe instance from a client/// process./// </summary>/// <param name="hHandle">Handle to an instance of a named pipe./// </param>/// <returns>If the function succeeds, the return value is nonzero./// </returns>[DllImport("kernel32.dll", SetLastError = true)]public static extern bool DisconnectNamedPipe(IntPtr hHandle);} // class PipeNative

C#端创建管道:

 private void ConnectPipe(string strPipeName){while (true){hPipe = PipeNative.CreateFile(strPipeName,  //管道名称FileDesiredAccess.GENERIC_READ | FileDesiredAccess.GENERIC_WRITE,  //访问模式,读模式或写模式FileShareMode.Zero,  //0表示不共享,共享模式IntPtr.Zero,  //一个只读字段,代表已初始化为零的指针或句柄。指向安全属性的指针FileCreationDisposition.OPEN_EXISTING, //如何创建。文件必须已经存在。由设备提出要求0,  //文件属性0);  //用于复制文件句柄,不使用模板if (hPipe.ToInt32() != PipeNative.INVALID_HANDLE_VALUE) break;//PipeNative.INVALID_HANDLE_VALUE = -1.管道创建失败if (PipeNative.GetLastError() != PipeNative.ERROR_PIPE_BUSY   //PipeNative.ERROR_PIPE_BUSY = 231|| PipeNative.WaitNamedPipe(strPipeName, 5 * 1000))       //在超时时间前管道的一个实例有效则返回非0,在超时时间内没有一个有效的实例,则返回0 {Console.WriteLine("无法连接管道:{0} ERROR:{1}", strPipeName, PipeNative.GetLastError());return;}}Console.WriteLine("管道{0}连接成功。", strPipeName);}


C++端创建管道

借用先人总结的创建过程:

1):服务器进程调用CreateNamedPipe函数来创建一个有名称的命名管道在创建命名管道的时候必须指定一个本地的命名管道名称。windows允许同一个本地的命名管道名称右多个命名管道实例。所以,服务器进程在调用CreateNamedPipe函数时必须指定最大允许的实例数(0-255).如果CreateNamedPipe函数成功返回后,服务器进程得到一个指向一个命名管道实例的句柄。

2):服务器进程就可以调用ConnectNamedPipe来等待客户的连接请求,这个ConnectNamedPipe既支持同步形式,又支持异步形式,若服务器进程以同步形式调用 ConnectNamedPipe函数,如果没有得到客户端的连接请求,则会一直等到客户端的连接请求。当该函数返回时,客户端和服务器之间的命名管道连接已经建立起来了。

3):这个时候服务器端就可以向客户端读(ReadFile)/写(WriteFile)数据了。

4):在已经建立连接的命名管道实例中,服务器进程就会得到一个指向该管道实例的句柄,这个句柄称之为服务器端句柄,同时服务端进程可以调用DisconnectNamedPipe函数,将一个管道实例与当前建立连接的客户端进程断开,从而可以重新连接到新的客户端进程。当然,服务器也可以调用CloseHandle来关闭一个已经建立连接的命名管道实例。

调用CreateNamedPipe函数:

HANDLE WINAPI CreateNamedPipe(

_In_     LPCTSTR               lpName,

_In_     DWORD                 dwOpenMode,

_In_     DWORD                 dwPipeMode,

_In_     DWORD                 nMaxInstances,

_In_     DWORD                 nOutBufferSize,

_In_     DWORD                 nInBufferSize,

_In_     DWORD                 nDefaultTimeOut,

_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes

);

该函数用来创建一个命名管道的实例,并返回这个命名管道的句柄。如果需要创建一个命名管道的多个实例,就需要多次调用CreateNamedPipe函数。

参数 lpName 为一个字符串,其格式必须为 \\.\pipe\pipeName,其中圆点 ”.” 表示的是本地机器,如果想要与远程的服务器建立连接,那么这个圆点位置处应指定这个远程服务器的名称,而其中的 “pipe” 这个是个固定的字符串,也就是说不能进行改变的,最后的 “pipename” 则代表的是我将要创建的命名管道的名称了,参数 dwOpenMode 用来指定管道的访问方式,重叠方式,写直通方式,还有管道句柄的安全访问方式。

具体代码如下

HANDLE creatpipe()
{setlocale(LC_ALL, "chs");  //解决显示中文问题CString strPipeName;strPipeName.Format(_T("\\\\%s\\pipe\\%s"), _T("."), _T("myPipe2"));SECURITY_ATTRIBUTES sa;sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)malloc(SECURITY_DESCRIPTOR_MIN_LENGTH);//为安全描述符分配内存空间InitializeSecurityDescriptor(sa.lpSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);//InitializeSecurityDescriptor函数的第二个参数必需是1SetSecurityDescriptorDacl(sa.lpSecurityDescriptor, TRUE, NULL, FALSE);//此函数用来设置DACL中的信息。如果一个DACL已经在security descriptor中存在,那么此DACL将被替换。sa.nLength = sizeof(sa);sa.bInheritHandle = TRUE;HANDLE hPipe = CreateNamedPipe(strPipeName,  //管道名称PIPE_ACCESS_DUPLEX,  //管道的访问模式,双向模式PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,  //安全访问模式,以消息流的形式写入管道,以消息流的方式从管道读取数据,等待方式为同步方式,即一直等待到一个连接建立PIPE_UNLIMITED_INSTANCES,  //最大实例数 0-255usize,  //输出缓冲区大小 usize,  //输入缓冲区大小 NMPWAIT_USE_DEFAULT_WAIT,  //超时数&sa  //命名管道的安全性);if (hPipe == INVALID_HANDLE_VALUE)  //指向一个命名管道的实力句柄   无效{_tprintf(L"error\n");//宽字符串exit(1);//程序结束时,返回1给系统}_tprintf(_T("创建管道:%s成功\n"), strPipeName);_tprintf(_T("等待连接.....\n"));BOOL bc = ConnectNamedPipe(hPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);  //若连接成功,则bc为true,否则为GetLastError的返回值if (!bc){_tprintf(_T("连接错误.\n"));CloseHandle(hPipe);exit(1);}printf("连接成功.\n");return hPipe;
}

两端管道创建完毕之后就可以进行读写操作了。

C#端:

如果创建一个管道进行连续写入和读出的话,有可能会出现写入快,读出慢。读出的数据会发生混乱。称为管道阻塞。因此,有连续写入读出得需求时,就要在读出一次数据后回发一个标志位告诉写入端读出成功可以写入,写入端继续写入,否则等待标志位的到来。

不同类型数据同时写入:

由于写入管道的是byte[],所以需要写入的数据必须先由各自类型转为byte[]。下面是C#端的转换函数:

Int转byte:

/// <summary>/// /// </summary>/// <param name="value"></param>/// <returns></returns>public byte[] intToBytes(int value){byte[] src = new byte[4];src[3] = (byte)((value >> 24) & 0xFF);src[2] = (byte)((value >> 16) & 0xFF);src[1] = (byte)((value >> 8) & 0xFF);src[0] = (byte)(value & 0xFF);return src;}

Int转byte方法2:

 public byte[] ConvertIntToByteArray(int m){byte[] arry = new byte[4];arry[0] = (byte)(m & 0xFF);arry[1] = (byte)((m & 0xFF00) >> 8);arry[2] = (byte)((m & 0xFF0000) >> 16);arry[3] = (byte)((m >> 24) & 0xFF);return arry;}

Byte转int:

/// <summary>/// /// </summary>/// <param name="src"></param>/// <param name="offset"></param>/// <returns></returns>public int bytesToInt(byte[] src, int offset){int value;value = (int)((src[offset] & 0xFF)| ((src[offset + 1] & 0xFF) << 8)| ((src[offset + 2] & 0xFF) << 16)| ((src[offset + 3] & 0xFF) << 24));return value;}

String转byte:

byte[] byte_XX = System.Text.Encoding.Default.GetBytes(int_XX);

float转byte:

byte[] byte_XX = BitConverter.GetBytes(float_XX);

乱入一下:

当需要一次发送不同类型的数据时,就需要将这些数据按每个数据类型的长度依次插入到byte数组当中。

编写测试代码可算出各类型所占字节数:

#include "iostream"
using namespace std;int main()
{cout<<sizeof(char)<<endl;
cout<<sizeof(short)<<endl;
cout<<sizeof(int)<<endl;
cout<<sizeof(float)<<endl;
cout<<sizeof(long)<<endl;
cout<<sizeof(double)<<endl;return 0;
}

结果为:

1

2

4

4

4

8

可见32位系统,vc编译器中,short占 2 字节,int 、float、long 都占 4 字节,

只有double 占8 字。指针长度和地址总线有关。因为指针记录的就是一个地址,那么32位的就是4字节,64位的就是8字节。

64位编译器和32为区别不大:

char :1个字节

char*(即指针变量): 8个字节

short int: 2个字节

int: 4个字节

unsignedint : 4个字节

float:  4个字节

double:   8个字节

long:   8个字节

longlong:  8个字节

unsignedlong:  8个字节


 言归正传:

依次插入byte数组参考Buffer.BlockCopy方法:

将指定数目的字节从起始于特定偏移量的源数组复制到起始于特定偏移量的目标数组。

publicstatic void BlockCopy (

Array src,

int srcOffset,

Array dst,

int dstOffset,

int count

)

参数

src

源缓冲区。

srcOffset

src 的字节偏移量。

dst

目标缓冲区。

dstOffset

dst 的字节偏移量。

count

要复制的字节数。

当要一次发送int型1,string型和float型5这三个数据,那么就要考虑string的长度。

具体代码如下:

int int_ S1_length = typecn.getStringLength(S1);//计算长度
byte[] byte_ S1_length = typecn.intToBytes(int_ S1_length);//转换为byte
System.Buffer.BlockCopy(byte_ S1_length, 0, writebuffer, 0, byte_CamID_length.Length);Int N1 = 1;
byte[] byte_N1 = typecn.intToBytes(N1);//转换为byte
System.Buffer.BlockCopy(byte_N1, 0, writebuffer, 4, byte_N1.Length);string S1 = "s";
byte[] byte_S1 = System.Text.Encoding.Default.GetBytes(S1);
System.Buffer.BlockCopy(byte_S1, 0, writebuffer, 8, byte_S1.Length);float F1 = 5;
byte[] byte_F1 = BitConverter.GetBytes(F1);
System.Buffer.BlockCopy(byte_F1, 0, writebuffer, 4+ int_ S1_length, byte_F1.Length);uint real_write = 0;bool writeresult;uint len_write = (uint)writebuffer.Length;writeresult = PipeNative.WriteFile(       //将从数据库读出的信息发给C++hPipe,writebuffer,len_write,out real_write,IntPtr.Zero);if (writeresult){Console.WriteLine("成功写入管道");}

C++端读数据:

和C#端写数据的思路是一样的,一次按顺序读出来。

当管道读出byte数组时,可以直接赋值给任意类型的数组,系统会自动进行类型转换。为方便恢复到原来的类型,我定义为char[].用memcpy就可按位读取并且进行类型转换。

举个memcpy的例子:

#include<string.h>
int main(
{char* s="GoldenGlobalView";char d[20];memcpy(d,s+12,4);//从第13个字符(V)开始复制,连续复制4个字符(View)d[4]='\0';//memcpy(d,s+12*sizeof(char),4*sizeof(char));也可printf("%s",d);getchar();return 0;
}

输出结果: View

从管道中读数据具体代码如下:

int int_ S1_length;
int N1;
string S1;
float F1; DWORD rlen = 0;BOOL rRead;char c[500] = {};rRead = ReadFile(hPipe,c,500,&rlen,0);if (rRead){printf("读出成功\n");}memcpy(&int_ S1_length, c,4);memcpy(&N1, c + 4, 4);memcpy(&S1, c + 8, int_ S1_length);memcpy(&F1, c + 8+ int_ S1_length, 4);

C#与C++进程间管道通信相关推荐

  1. linux下进程间管道通信,Linux下进程间通信方式-管道

    本文关键字: linux 管道通信,linux 进程通信方式,无名管道,有名管道 管道是Linux中进程间通信的一种方式,它把一个程序的输出直接连接到另一个程序的输入.Linux的管道主要包括两种:无 ...

  2. 进程间的通信IPC(无名管道和命名管道)

    进程间的通信IPC介绍 进程间通信(IPC,InterProcess Communication)是指在不同进程之间传播或交换信息. IPC的方式通常有管道(包括无名管道和命名管道).消息队列.信号量 ...

  3. 进程间的通信——无名管道

    进程间的通信--无名管道 宗旨:技术的学习是有限的,分享的精神是无限的. 一.进程间的通信 (1)同主机进程间数据交互机制:无名管道(PIPE),有名管道(FIFO).消息队列和共享内存.无名管道多用 ...

  4. 网络编程之 进程间的通信之管道的使用

    如何使用管道是进程间通信的关键 博主先声明一下,关于处理进程创建以及销毁的方法.        "子进程究竟何时终止????调用waitpid函数后还要无休止的等待子进程终止吗???&quo ...

  5. 命名管道(FIFO) Linux进程进程间的通信之命名管道(FIFO)

    Linux进程进程间的通信之命名管道(FIFO) 命名管道(FIFO),它和一般的管道一样.都是作为中间的邮递员来实现两个进程间的通信交流. 命名管道(FIFO)有几个特点: 1.命名管道(FIFO) ...

  6. 【操作系统】进程间的通信——管道

    进程间的通信-管道 管道 进程间的通信(IPC-Inter-Process Communication)有多种方式,管道是其中最基本的方式. 管道是半双工的,即是单向的. 管道是FIFO(先进先出)的 ...

  7. 2022.8.31 进程中无名管道的特点,无名管道的创建,为何无名管道只能能够实现具有亲缘关系的进程间的通信,以及实现利用无名管道父进程给子进程发送消息的完整代码。

    无名管道通信 无名管道特点: (1):只能用于具有亲缘关系的进程之间的通信.(父子进程或兄弟进程) (2):是一个半双工的通信模式,具有固定的读端和写端.(fd[0]固定为读端,fd[1]固定为写端) ...

  8. 进程间的通信--无名管道

    无名管道是 UNIX 系统 IPC(进程间通信)的最古老形式,所有 UNIX 系统都支持这种通信方式机制 管道的特点: 半双工,数据在同一时刻只能在一个方向上流懂 数据只能从管道的一段写入,另一端读出 ...

  9. Linux系统编程(三)进程间的通信

    Linux系统编程(三)进程间的通信 一.为什么需要进程之间的通信(IPC)? 二.管道 1.概念 2.特质 3.原理 4.局限性 5.代码 2.读入数据 三.共享存储映射 注意事项 父子进程通信 一 ...

最新文章

  1. 多线程 阻塞队列中的poll与take区别
  2. c++后台管理系统_【获奖案例】第三届全国医院物联网大会“中国医院物联网应用十大优秀案例”安徽医科大学第一附属医院手术室行为管理系统...
  3. vista装不了SQL SERVER
  4. perl语言编程 第四版_2020年,5 种 将死的编程语言
  5. monk js_对象检测-使用Monk AI进行文档布局分析
  6. 在laravel中,使用DB查询数据库后,返回的对象转为数组
  7. L323 英语有必要学语法吗
  8. 图虫知识共享协议_缘之好物 篇二十:关怀父母的另类方案----新礼物:2019图虫影像历...
  9. [Android] Android开机启动Activity或者Service方法
  10. 拓端tecdat|R语言生存分析数据分析可视化案例
  11. Luogu1856 [USACO5.5]矩形周长Picture(矩形周长并)
  12. 世界各国英文简写一览表
  13. 【安卓按键精灵】教你一个小时自己开发脚本,零基础1个小时上手
  14. 电机驱动软件学习笔记——数据打包解包CRC校验
  15. CodeSmith(C#)简单示例及相关小知识
  16. 常用GIS(高清卫星影像、DEM)数据下载
  17. DM642的PCI驱动编程笔记:遍历一块内存空间的源码
  18. Ubuntu与arm开发板之间构建NFS数据通道
  19. 十四、C指针详解(四):指针的指针
  20. python 椭圆曲线_椭圆曲线double和add在python中的实现

热门文章

  1. LTE学习理解系列——利用matlab工具生成4G LTE信源
  2. java 二分图带权匹配_算法笔记_139:二分图的最大权匹配(Java)
  3. 【LeetCode题目详解】(二)206.反转链表、876.链表的中间结点
  4. 一专科生逆袭入职腾讯,真是小母牛坐飞机,牛逼上天了啊
  5. 【ATF】林伟:大数据计算平台的研究与实践
  6. html打印预览首行缩进样式无效,css首行缩进没有效果的原因及解决办法
  7. hadoop集群部署
  8. 终于弄明白了二极管在BUCK与BOOST电路中的作用!
  9. ubuntu搭建NTP服务器
  10. python实现概率质量函数Poisson