命名管道

“命名管道”又名“命名管线”(Named Pipes),是一种简单的进程间通信(IPC)机制,Microsoft Windows大都提供了对它的支持(但不包括Windows CE)。命名管道可在同一台计算机的不同进程之间或在跨越一个网络的不同计算机的不同进程之间,支持可靠的、单向或双向的数据通信。推荐用命名管道作为进程通信方案的一项重要的原因是它们充分利用了Windows内建的安全特性(ACL等)。
用命名管道来设计跨计算机应用程序实际非常简单,并不需要事先深入掌握底层网络传送协议(如TCP、UDP、IP、IPX)的知识。这是由于命名管道利用了微软网络提供者(MSNP)重定向器通过同一个网络在各进程间建立通信,这样一来,应用程序便不必关心网络协议的细节。

命名管道基本信息

中文名 命名管道 外文名 Named Pipes
支持平台 Windows,Linux,Unix等

序言

我们会对命名管道已知的所有问题及限制进行总结.

实例1

在一个程序中实现命名管道的创建与使用

实例2

此示例代码意在体现出命名管道与普通管道的区别,命名管道是以一个普通文件的形式出现的,包括三个文件,创建命名管道、写管道、读管道

1. 创建命名管道

#include<sys/types.h>

#include<sys/stat.h>

#include<unistd.h>

#include<fcntl.h>

int main(void){

char buf[80];

int fd;

unlink("zieckey_fifo");

mkfifo("zieckey_fifo",0777);}写命名管道代码

#include<sys/types.h>

#include<sys/stat.h>

#include<unistd.h>

#include<fcntl.h>

int main(void){

int fd;

char s[]="Hello!\n";

fd=open("zieckey_fifo",O_WRONLY);

while(1){

write(fd,s,sizeof(s));

sleep(1);}

return0;

}

读命名管道代码

#include<sys/types.h>

#include<sys/stat.h>

#include<unistd.h>

#include<fcntl.h>

int main(void){

int fd;

char buf[80];

fd = open("zieckey_fifo",O_RDONLY);

while(1){

read(fd,buf,sizeof(buf));

printf("%s\n",buf);

sleep(1); }

return0;

}

命名管道造价信息

市场价 信息价 询价
材料名称 规格/型号 市场价
(除税)
工程建议价
(除税)
行情 品牌 单位 税率 供应商 报价日期
管道 公称直径DN(mm):50,规格型号:24 查看价格 查看价格

卓奥

m 13% 江苏卓奥节能设备安装工程有限公司浙江办事处
管道式换气扇 DPT20-54B 风量:770m3/H;功率:0.145KW;噪声:35DB(A),风压:200PA 查看价格 查看价格

雄吉通风

13% 重庆市雄吉通风设备股份有限公司
给水用钢丝网增强聚乙烯复合管道1.6MPA Ф200 查看价格 查看价格

顾地

m 13% 重庆顾地塑胶电器有限公司
管道及附件 包含系统内所含的管道、弯头、三通、法兰等 查看价格 查看价格

13% 上海熊猫机械(集团)有限公司
钢纤增强聚乙烯复合压力管道(含聚氨酯保温层及PE外护套) DN200×8.5 1.6MPa 查看价格 查看价格

粤星管道

m 13% 广东建通管道制品有限公司
钢纤增强聚乙烯复合压力管道(含聚氨酯保温层及PE外护套) DN350×13 1.6MPa 查看价格 查看价格

粤星管道

m 13% 广东建通管道制品有限公司
给水用钢丝网增强聚乙烯复合管道1.6MPA Ф160 查看价格 查看价格

顾地

m 13% 重庆顾地塑胶电器有限公司
钢纤增强聚乙烯复合压力管道(含聚氨酯保温层及PE外护套) DN100×6.5 1.6MPa 查看价格 查看价格

粤星管道

m 13% 广东建通管道制品有限公司
材料名称 规格/型号 除税
信息价
含税
信息价
行情 品牌 单位 税率 地区/时间
环卫管道疏通机 功率1.5(kW) 查看价格 查看价格

台班 韶关市2010年8月信息价
9A151 查看价格 查看价格

台班 汕头市2012年4季度信息价
功率120kW 查看价格 查看价格

台班 汕头市2012年4季度信息价
功率160kW 查看价格 查看价格

台班 汕头市2012年4季度信息价
9A151 查看价格 查看价格

台班 汕头市2012年3季度信息价
功率240kW 查看价格 查看价格

台班 汕头市2012年3季度信息价
功率120kW 查看价格 查看价格

台班 汕头市2012年3季度信息价
9A151 查看价格 查看价格

台班 汕头市2012年1季度信息价
材料名称 规格/需求量 报价数 最新报价
(元)
供应商 报价地区 最新报价时间
变压器命名 变压器命名牌|1台 1 查看价格 广西  来宾市 2012-12-04
管道系统 包括进出水管道、药剂输送管道、污泥管道、自来水管道、压缩空气|1项 1 查看价格 广东岑安机电有限公司 全国   2022-08-02
命名 命名牌 型号规格:方通龙骨+木纹铝板 仿木纹色+深褐色 500x200xH2100|9个 3 查看价格 广东双子标识科技有限公司 广东   2020-11-17
管道支架 管道支架|1000kg 1 查看价格 广州珠江管业科技有限公司 广东  广州市 2019-07-05
管道支架 管道支架|100kg 1 查看价格 广州珠江管业科技有限公司 广东  广州市 2019-07-05
管道清理疏通 含吸污车吸取、运输,管道冲洗|12000m 1 查看价格 成都美妙一环保工程有限公司 四川   2022-07-12
CPVC管道 种类 CPVC 公称外径 20(mm) 壁厚 2.4(mm) 长度 4(m) 拉伸强度 10(MPa) 用途 化工管道 每件重量 0.5(kg)|5890m 1 查看价格 睿智昊通管道阀门(北京)有限公司 北京  北京市 2015-03-30
管道(组合管道) 侧向+纵向抗震支架,SXZ-7,具体参数详见图纸|5套 3 查看价格 喜利得中国商贸有限公司 广东  深圳市 2019-12-04

假定有一台服务器保存着公司的秘密,我们要求只有公司的管理人员才能访问或编辑这些秘密(高权限信息)。而在自己的工作网络,公司内的每名员工都可看到网络上的这台计算机(低权限访问)。然而,我们并不希望普通员工(低权限组)取得对机密材料的访问权。公司要求我们开发一个数据管理系统,此系统只允许一个指定的用户组(高权限组)进行操作。

在这种情况下,命名管道等包含ACL的数据通信系统可发挥作用。因为我们可利用ACL,使只有拥有特别权限的用户(高权限组)与指定服务器发送控制信息,以此对公司的秘密进行操作。在此要记住的一个重点是:将命名管道作为一种网络编程方案使用时,它实际上建立一个简单的客户机/服务器数据通信体系(通常是TCP/IP,TCP协议具有良好的稳定性与数据安全性)。

要学习开发一组命名管道应用(可能是一个进程的不同线程、同一个可执行性文件的不同实例或完全不同的程序),首先要了解命名管道的命名规范(命名协议),然后了解基本的管道类型,接着实现一组简单的服务器应用与一个客户端应用。然后再以它为基础,深入研究高级的服务器编程技术,了解更复杂的通信系统与简单的通信协议。

在计算机编程里,命名管道是一种从一个进程到另一个进程用内核对象来进行信息传输。和一般的管道不同,命名管道可以被不同进程以不同的方式方法调用(可以跨权限、跨语言、跨平台)。只要程序知道命名管道的名字,发送到命名管道里的信息可以被一切拥有指定授权的程序读取,但对不具有制定授权的。命名管道是一种FIFO(先进先出,First-In First-Out)对象。

命名管道常见问题

命名管道(NamedPipe)是服务器进程和一个或多个客户进程之间通信的单向或双向管道。不同于匿名管道的是:命名管道可以在不相关的进程之间和不同计算机之间使用,服务器建立命名管道时给它指定一个名字,任何进程都可以通过该名字打开管道的另一端,根据给定的权限和服务器进程通信。命名管道提供了相对简单的编程接口,使通过网络传输数据并不比同一计算机上两进程之间通信更困难,不过如果要同时和多个进程通信它就力不从心了。

命名管道实例1

在一个程序中实现命名管道的创建与使用。

#include
 
  
#include
  
    #include
   
     #include
    
      intmain( void) { charbuf[80]; intfd; unlink("zieckey_fifo");mkfifo("zieckey_fifo",0777); if( fork()>0) { chars[]="Hello! "; fd=open("zieckey_fifo",O_WRONLY); write(fd,s,sizeof(s)); //close(fd); } else { fd=open("zieckey_fifo",O_RDONLY); read(fd,buf,sizeof(buf));printf("Themessagefromthepipes:%s ",buf); //close(fd); } return0; } /*执行结果为 Themessagefromthepipes:Hello! 并且可以在程序执行目录生成管道文件zieckey_fifo */
    
   
  
 

命名管道实例2

此示例代码意在体现出命名管道与普通管道的区别,命名管道是以一个普通文件的形式出现的,包括三个文件操作:创建命名管道、写管道、读管道。

1. 创建命名管道

#include
 
  #include
  
   #include
   
    #include
    
     intmain(void){charbuf[80];intfd;unlink("zieckey_fifo");mkfifo("zieckey_fifo",0777);} 
    
   
  
 

写命名管道代码

#include
 
  #include
  
   #include
   
    #include
    
     intmain(void){intfd;chars[]="Hello! ";fd=open("zieckey_fifo",O_WRONLY); while (1){ write(fd,s,sizeof(s)); sleep(1); }return0;} 
    
   
  
 

读命名管道代码

#include
 
  #include
  
   #include
   
    #include
    
     intmain(void){intfd;charbuf[80];fd=open("zieckey_fifo",O_RDONLY);while(1){read(fd,buf,sizeof(buf));printf("%s ",buf);sleep(1);}return0;}
    
   
  
 

命名管道文献

PDMS管道命名规则 PDMS管道命名规则

格式:pdf

大小:416KB

页数: 58页

评分: 4.7

PLEASE NOTE: CADCentre has a policy of continuing product development: therefore, the information contained in this document may be subject to change without notice. CADCENTRE MAKES NO WARRANTY OF ANY KIND WITH REGARD TO THIS DOCUMENT, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. While every effort has been made to verify the

立即下载
管道与管道附件知识 管道与管道附件知识

格式:pdf

大小:416KB

页数: 48页

评分: 4.8

맜뗀폫맜뗀뢽볾쿠맘횪쪶 튻ꆢ맜뗀 1 ꆢ맜뗀ꎺ평맜뗀ퟩ볾ꆢ횧볜ꆢ뢽쫴짨쪩ퟩ돉ꎬ폃틔쫤쯍ꆢ럖엤ꆢ믬뫏ꆢ럖샫ꆢ 업럅ꆢ볆솿ꆢ 뿘훆믲훆횹쇷쳥쇷뚯뗄맜ퟓꆢ맜볾ꆢ 램삼ꆢ식쮨솬뷓ꆢ 뗦욬ꆢ랧쏅뫍웤쯼ퟩ돉볾믲쫜톹늿볾뗄ힰ엤ퟜ돉ꆣ 맜뗀ퟩ돉볾ꎺ폃폚솬뷓믲ힰ엤맜뗀뗄풪볾ꆣ쯼냼삨맜ퟓꆢ맜볾ꆢ램삼ꆢ뗦 욬ꆢ뷴만볾ꆢ랧쏅틔벰엲헍뷓춷ꆢ쓓탔뷓춷ꆢ쓍톹죭맜ꆢ쫨쮮웷ꆢ 맽싋웷뫍럖샫웷뗈ꆣ 뢽쫴짨쪩ꎺ볬닩뺮 맜뗀횧돐볾ꎺ맜뗀낲ힰ볾ꆢ뢽ퟅ볾ꆣ 쫤쯍뗄뷩훊폐ꎺ웸쳥ꆢ튺쳥ꆢ뿅솣 2 ꆢ맜뗀뗄럖샠 * 튻냣럖죽듳샠ꎺ 릤튵맜뗀ꎺ웳쫂튵떥캻폃폚쫤쯍릤틕뷩훊뗄릤틕맜뗀ꆢ릤돌맜뗀벰웤쯼뢨훺 맜뗀ꎺ쮮ꆢ웸ꆢ폍 ---뮯톧욷---쇷쳥---뿅솣컯 릫폃맜뗀ꎺ 릫폃쫂튵믲쏱폃뗄ꎺ 쫤쯍좼웸ꆢ죈솦 뎤쫤맜뗀ꎺ 닺뗘ꆢ뒢듦뿢ꆢ 폃뮧볤뗄폃폚쫤쯍짌욷뷩훊뗄맜뗀ꎺ 쪯폍ꆢ쳬좻웸 * 내헕톹솦럖ꎺ *내헕컂뛈럖ꎺ *맜뗀럖벶ꎺ 3 ꆢ맜뗀

立即下载

命名管道程序设计的实现

1.命名管道Server和Client间通信的实现流程

(1)建立连接:服务端通过函数CreateNamedPipe创建一个命名管道的实例并返回用于今后操作的句柄,或为已存在的管道创建新的实例。如果在已定义超时值变为零以前,有一个实例管道可以使用,则创建成功并返回管道句柄,并用以侦听来自客户端的连接请求,该功能通过ConnectNamedPipe函数实现。

另一方面,客户端通过函数WaitNamedPipe使服务进程等待来自客户的实例连接,如果在超时值变为零以前,有一个管道可以为连接使用,则WaitNamedPipe将返回True,并通过调用CreateFile或CallNamedPipe来呼叫对服务端的连接。此时服务端将接受客户端的连接请求,成功建立连接,服务端ConnectNamedPipe返回True,客户端CreateFile将返回一指向管道文件的句柄。

从时序上讲,首先是客户端通过WaitNamedPipe使服务端的CreateFile在限时时间内创建实例成功,然后双方通过ConnectNamedPipe和CreateFile成功连接,并返回用以通信的文件句柄,此时双方即可进行通信。

(2)通信实现:建立连接之后,客户端与服务器端即可通过ReadFile和WriteFile,利用得到的管道文件句柄,彼此间进行信息交换。

(3)连接终止:当客户端与服务端的通信结束,或由于某种原因一方需要断开时,客户端应调用CloseFile,而服务端应接着调用DisconnectNamedPipe。当然服务端亦可通过单方面调用DisconnectNamedPipe终止连接。最后应调用函数CloseHandle来关闭该管道。

命名管道服务器端和客户端代码实现

客户端

HANDLE CltHandle;

char pipenamestr[30];

sprintf(pipenamestr,″\\servername\pipe\pipename″)

if (WaitNamedPipe( pipenamestr, NMPWAIT—WAIT—FOREVER)==FALSE

// 管道名要遵循UNC,格式为\ \.\pipe\pipname,名字不分大小写。

AfxMessageBox(″操作失败,请确定服务端正确建立管道实例!″);

Else

CltHandle=CreateFile(pipenamestr, GENERIC—READ|GENERIC—WRITE, FILE—SHARE—READ| FILE—SHARE—WRITE,NULL, OPEN—EXISTING,

//为了与命名管道连接,此参数应一直为OPEN—EXISTING

FILE—ATTRIBUTE—ARCHIVE|FILE—FLAG—WRITE—THROUGH,

// FILE—FLAG—WRITE—THROUGH会使管道WriteFile调用处于阻塞状态,直到数据传送成功。

NULL);

If (CltHandle== INVALID—HANDLE—VALUE)

AfxMessageBox(″管道连接失败″);

Else

DoUsertTransactInfo();

//执行用户自定义信息交换函数——从管道读、写信息。

……

服务端

HANDLE SvrHandle;

char pipenamestr[30];

sprintf(pipenamestr,″\\.\pipe\pipename″)

SvrHandle=CreateNamedPipe(pipenamestr,

PIPE—ACCESS—DUPLEX|FILE—FLAG—WRITE—THROUGH,

//阻塞模式,这种模式仅对″字节传输管道″操作有效。

FILE—WAIT|PIPE—TYPE—BYTE,

//字节模式

PIPE—UNLIMITED—INSTANCES,

128,128,

NULL,NULL);

// SECURITY—ATTRIBUTES结构指针,描述一个新管道,确定子进程的继承权,如果为NULL则该命名管道不能被继承。

If (SvrHandle==INVALID—HANDLE—VALUE)

AfxMessageBox(″管道创建失败,请确定客户端提供连接可能!″);

Else

If (ConnectNamedPipe(SvrHandle,NULL)==FALSE)

AfxMessageBox(″建立连接失败!″);

Else

DoUsertTransactInfo();

//用户自定义信息交换函数

……

使用灵活性

命名管道具有很好的使用灵活性,表现在:

1) 既可用于本地,又可用于网络。

2) 可以通过它的名称而被引用。

3) 支持多客户机连接。

4) 支持双向通信。

5) 支持异步重叠I/O操作。

不过,当前只有Windows NT支持服务端的命名管道技术。

命名管道是由服务器端的进程建立的,管道的命名必须遵循特定的命名方法,就是 "\\.\pipe\管道名",当作为客户端的进程要使用时,使用"\\计算机名\\pipe\管道名" 来打开使用,具体步骤如下:

服务端通过函数 CreateNamedPipe 创建一个命名管道的实例并返回用于今后操作的句柄,或为已存在的管道创建新的实例。 服务端侦听来自客户端的连接请求,该功能通过 ConnectNamedPipe 函数实现。 客户端通过函数 WaitNamedPipe 来等待管道的出现,如果在超时值变为零以前,有一个管道可以使用,则 WaitNamedPipe 将返回 True,并通过调用 CreateFile 或 CallNamedPipe 来呼叫对服务端的连接。 此时服务端将接受客户端的连接请求,成功建立连接,服务端 ConnectNamedPipe 返回 True 建立连接之后,客户端与服务器端即可通过 ReadFile 和 WriteFile,利用得到的管道文件句柄,彼此间进行信息交换。 当客户端与服务端的通信结束,客户端调用 CloseFile,服务端接着调用 DisconnectNamedPipe。最后调用函数CloseHandle来关闭该管道。 由于命名管道使用时作为客户端的程序必须知道管道的名称,所以更多的用在同一"作者"编写的服务器/工作站程序中,你不可能随便找出一个程序来要求它和你写的程序来通过命名管道通信。而匿名管道的使用则完全不同,它允许你和完全不相干的进程通信,条件是这个进程通过控制台"console"来输入输出,典型的例子是老的 Dos 应用程序,它们在运行时 Windows 为它们开了个 Dos 窗口,它们的输入输出就是 console 方式的。还有一些标准的 Win32 程序也使用控制台输入输出,如果在 Win32 编程中不想使用图形界面,你照样可以使用 AllocConsole 得到一个控制台,然后通过 GetStdHandle 得到输入或输出句柄,再通过 WriteConsole 或 WriteFile 把结果输出到控制台(通常是一个象 Dos 窗口)的屏幕上。虽然这些程序看起来象 Dos 程序,但它们是不折不扣的 Win32 程序,如果你在纯 Dos 下使用,就会显示"The program must run under Windows!"。

一个控制台有三个句柄:标准输入、标准输出和和标准错误句柄,标准输入、标准输出句柄是可以重新定向的,你可以用匿名管道来代替它,这样一来,你可以在管道的另一端用别的进程来接收或输入,而控制台一方并没有感到什么不同,就象 Dos 下的 > 或者 < 可以重新定向输出或输入一样。通常控制台程序的输入输出如下:

(控制台进程output) write ----> 标准输出设备(一般是屏幕)

(控制台进程input) read <---- 标准输入设备(一般是键盘)

而用管道代替后:

(作为子进程的控制台进程output) write ----> 管道1 ----> read (父进程)

(作为子进程的控制台进程input) read <----> 管道2 <---- write (父进程)

使用匿名管道的步骤如下:

使用 CreatePipe 建立两个管道,得到管道句柄,一个用来输入,一个用来输出 准备执行控制台子进程,首先使用 GetStartupInfo 得到 StartupInfo 使用第一个管道句柄代替 StartupInfo 中的 hStdInput,第二个代替 hStdOutput、hStdError,即标准输入、输出、错误句柄 使用 CreateProcess 执行子进程,这样建立的子进程输入和输出就被定向到管道中 父进程通过 ReadFile 读第二个管道来获得子进程的输出,通过 WriteFile 写第一个管道来将输入写到子进程 父进程可以通过 PeekNamedPipe 来查询子进程有没有输出 子进程结束后,要通过 CloseHandle 来关闭两个管道。 下面是具体的说明和定义:

1. 建立匿名管道使用 CreatePipe 原形如下:

BOOL CreatePipe(

PHANDLE hReadPipe, // address of variable for read handle

PHANDLE hWritePipe, // address of variable for write handle

LPSECURITY_ATTRIBUTES lpPipeAttributes, // pointer to security attributes

DWORD nSize // number of bytes reserved for pipe

);

当管道建立后,结构中指向的 hReadPipe 和 hWritePipe 可用来读写管道,当然由于匿名管道是单向的,你只能使用其中的一个句柄,参数中的 SECURITY_ATTRIBUTES 的结构必须填写,定义如下:

typedef struct_SECURITY_ATTRIBUTES{

DWORD nLength: //定义以字节为单位的此结构的长度

LPVOID lpSecurityDescriptor; //指向控制这个对象共享的安全描述符,如果为NULL这个对象将被分配一个缺省的安全描述

BOOL bInheritHandle; //当一个新过程被创建时,定义其返回是否是继承的.供系统API函数使用.

}SECURITY_ATTRIBUTES;

2. 填写创建子进程用的 STARTUPINFO 结构,一般我们可以先用 GetStartupInfo 来填写一个缺省的结构,然后改动我们用得到的地方,它们是:

hStdInput -- 用其中一个管道的 hWritePipe 代替 hStdOutput、hStdError -- 用另一个管道的 hReadPipe 代替 dwFlags -- 设置为 STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW 表示输入输出句柄及 wShowWindow 字段有效 wShowWindow -- 设置为 SW_HIDE,这样子进程执行时不显示窗口。 填写好以后,就可以用 CreateProcess 来执行子进程了,具体有关执行子进程的操作可以参考上一篇教程《进程控制》

3. 在程序中可以用 PeekNamedPipe 查询子进程有没有输出,原形如下:

BOOL PeekNamedPipe(

HANDLE hNamedPipe, // handle to pipe to copy from

LPVOID lpBuffer, // pointer to data buffer

DWORD nBufferSize, // size, in bytes, of data buffer

LPDWORD lpBytesRead, // pointer to number of bytes read

LPDWORD lpTotalBytesAvail, // pointer to total number of bytes available

LPDWORD lpBytesLeftThisMessage // pointer to unread bytes in this message

);

我们可以将尝试读取 nBuffersize 大小的数据,然后可以通过返回的 BytesRead 得到管道中有多少数据,如果不等于零,则表示有数据可以读取。

4. 用 ReadFile 和 WriteFile 来读写管道,它们的参数是完全一样的,原形如下:

ReadFile or WriteFile(

HANDLE hFile, // handle of file to read 在这里使用管道句柄

LPVOID lpBuffer, // address of buffer that receives data 缓冲区地址

DWORD nNumberOfBytesToRead, // number of bytes to read 准备读写的字节数

LPDWORD lpNumberOfBytesRead, // address of number of bytes read,实际读到的或写入的字节数

LPOVERLAPPED lpOverlapped // address of structure for data 在这里用 NULL

);

5. 用 CloseHandle 关闭管道一和管道二的 hReadPipe和 hWritePipe 这四个句柄。

下面给出了一个例子程序,这个程序是上篇教程《进程控制》的例子的扩充,如果你对有的 api 感到陌生的话,请先阅读上一篇教程。

命名管道相关推荐
  • 相关百科
  • 相关知识
  • 相关专栏