命名管道(Named Pipe)服务

1  命名管道的名称解析

在Windows中,管道的名称遵循Windows统一命名规范(UNC,Universal Naming Convention)。

命名管道的名称格式为\\<Server>\Pipe\<PipeName>。<Server>指定了一个命名管道的服务器所在的计算机名称,既可以是DNS名称,也可以是NetBIOS名称或者字符串形式的IP地址;<PipeName>是管道的唯一名,可以是层次结构中的一个全路径名,即允许包含多级目录。例如:\\MyServer\Pipe\MyAppServer\ConnectionPipe。

使用CreateNamedPipe API创建命名管道时,必须指定一个形如\\.\Pipe\<PipeName>的本地名称,“.”代表本地系统。NtCreateNamedFile 接收到的名称为“\??\PIPE\<PipeName>”,对象管理器会将此名称变为”\Global??\PIPE\<PipeName>”,”\Global??\PIPE”是一个符号链接,指向设备对象”\Device\NamedPipe”,对象管理器找到该设备对象,由它所属的驱动程序进一步解析剩下的子串,这就进入到了命名管道驱动程序中。

命名管道实际上是本地的一个文件系统,npfs就代表了命名管道文件系统(named pipe file system) 。每个命名管道等同于一个文件对象,与普通文件系统中的文件不同的是,命名管道是动态对象,它没有永久状态。一个命名管道的存在总是伴随着一个服务器和一个客户,其职责是为服务器和客户提供一个双向交换数据的通道。

2  命名管道的通讯模型

如图:

  1. 服务器进程调用CreateNamePipe 创建一个有名称的命名管道,同时指定最大允许的实例数(1~255)。
  2. 服务器进程调用ConnectNamedPipe,以等待客户的连接请求,可以是同步形式(阻塞)或异步方式(要求在创建命名管道时指定了FILE_FLAG_OVERLAPPED标志),若是同步方式,那么ConnectNamedPipe返回时,客户与服务器之间的名叫管道连接已经建立起来。
  3. 客户进程调用CreateFile 连接到一个正在等待连接的命名管道上。CreateFile 成功返回后,至此服务器进程的ConnectNamedPipe 完成其建立连接的任务。
  4. 双方调用ReadFile/WriteFile 或ReadFileEx/WriteFileEx ,从管道中读取或写入数据。

服务器进程可以调用DisconnectNamedPipe ,将一个管道实例与当前建立连接的客户进程断开,可以重新连接到新的客户进程。CloseHandle 关闭命名管道。

客户进程调用WaitNamedPipe 测试指定名单的管道实例是否可用。

命名管道支持字节模式和消息模式,服务器进程在创建命名管道时指定它的默认模式。

服务器和客户进程都可以调用SetnamedPipeHandleState 设置命名管道实例的读操作模式和等待模式。若服务器指定了管道为字节模式,则客户端不能设置消息模式;若服务器指定了消息模式,则客户端允许将它这一端设置为字节模式。

TransactnamedPipe 只能用于消息模式的命名管道,它将一个写和读消息操作合并为一个网络操作。客户和服务器进程都可以使用它。

CallnamedPipe 等价于先调用CreateFile 建立命名管道实例连接,然后调用TransactNamedPipe 发送和接收消息,最后调用CloseHandle 关闭命名管道实例。仅用于客户进程。

管道字节模式的时候是以字节流接收与发送的。每次可以发送不同的字节数,在没有把发送的数据收走(用ReadFile)前也可以再次发送,只要没有超过管道的默认的缓冲区大小 。其实也可以说是我们用的是PIPE_WAIT,所以会是在阻塞模式,也就是说会让数据直接发送到了服务器端的缓冲区中,虽然sever端没有调用ReadFile来读取数据,其实已经发到那一边去了,它不读出来没有关系,我们客户端还是可以继续发送数据的。而且对每次发送的数据大小没有限制,不会说每次都得发送固定大小的数据 。读的那一端也会把接收到的数据作为一个无机的整体,也就是说是没有结构的二进制流。读的时候可以想读出任意的字节数都可以的。如一次发送了5个字节,然后再发送了40个字节 ,服务器端可以一次性全部读出45个字节 也可以每次读出一个字节 。以及小于45的任意字节。

3  命名管道的实现

服务器创建命名管道过程:

  1. CreateNamedPipe 创建命名管道的请求交给NtCreateNamedPipeFile。
  2. NtCreateNamedPipeFile 接收到的命名管道的名称未”\??\PIPE\<PipeName>”,该函数把参数组织到一个NAMED_PIPE_CREATE_PARAMETERS结构中,然后调用IoCreateFile 创建任务。
  3. IoCreateFile 中指定CREATE_FILE_TYPE参数,表明是要创建的文件类型:普通的文件、命名管道或者邮件槽。然后,IoCreateFile调用IopCreateFile 。
  4. IopCreateFile 调用ObOpenObjectByName 完成创建工作。
  5. ObOpenObjectByName继续调用ObpLookupObjectName 创建目标对象。
  6. ObpLookupObjectName 判断命名管道的名称名称以“\??\”为前缀,于是从进程对象的DeviceMap 的DosDeviceDirectory 开始解析余下的名称。
  7. 经过”\??\”解析后,接着从“\Global??”目录中解析”PIPE”,这是一个指向设备对象”\Device\NamedPipe”的符号链接对象。符号链接对象的数据类型为OBJECT_SYMBOLIC_LINK,其Parse 方法为ObpParseSymbolicLink。
  8. ObpLookupObjectName 调用ObpParseSymbolicLink 解析余下的名称”<PipeName>”。 ObpParseSymbolicLink 返回STATUS_REPARSE,ObpLookupObjectName重新解析“\Devuce\NamedPipe\<PipeName>”,故重新从根目录开始解析,,最后找到设备对象”\Device\NamedPipe”。接着调用IopParseDevice。
  9. IopParseDevice 调用ObCreateObject 创建一个文件对象(FILE_OBJECT),然后通过IoCallDriver,向设备对象的驱动程序npfs.sys 发送一个IRP_MJ_CREATE_NAMED_PIPE请求,来创建命名管道。
  10. 命名管道驱动程序初始化设备对象“\Device\NamedPipe”,并设置驱动程序对象的I/O分发例程。

Npfs.sys 的内部实现有一个全局的VCB和根目录的DCB,每个管道对象有一个FCB,命名管道的每个实例有一个CCB,每个CCB有两个文件对象指针,分别指向该实例的服务端和客户端文件对象。因为每个命名管道对象可以有多个实例,所以FCB有一个链表成员,将它的所有实例的CCB链接起来。为了提供双向数据传输能力,每个CCB,即命名管道实例,包含两个队列结构,用做数据传输的缓冲区。

命名管道的实现示意图:

服务端通过NtCreateNamedPipe 来创建命名管道,通过对象管理器发送IRP_MJ_CREATE_NAMED_PIPE请求。Npfs.sys 接收到该请求时,若是一个新的命名管道,则创建一个FCB和一个CCB,并初始化FCB,以及CCB中有关服务端的状态;若是已有的命名管道,则npfs 创建一个CCB,将其加入到FCB的CCB链表中,并初始化CCB的服务端状态。

客户端连接服务端:

  1. 客户进程通过NtCreateFile 连接命名管道时,它通过对象管理器,向命名管道驱动发送IRP_MJ_CREATE请求。
  2. Npfs.sys 接收到此请求时,通过解析指定的名称,找到FCB,然后找到一个处于监听状态的CCB,并初始化它的客户端状态信息,最后将它置为”已建立连接”的状态。

双方收发数据:

  1. 服务器和客户端通过NtReadFile 和NtWriteFile ,根据文件对象的指示,向驱动程序发送IRP_MJ_READ 或IRP_MJ_WRITE请求。
  2. Nptfs 驱动程序利用CCB中的两个数据队列来实现基于管道实例的读写操作,并且支持字节模式和消息模式。

命名管道实际上是一个内存中的文件对象,供不同程序之间传递数据或消息。

命名管道(Named Pipe)服务相关推荐

  1. 浅析Windows命名管道Named Pipe

    目录 管道 命名管道Names Pipes 查看管道列表 命名管道的创建与访问 命名管道的利用 绕过防火墙 模拟令牌(System权限) C2 信道 MS17010和Named Pipe 管道 讲命令 ...

  2. mysql 的命名管道_SQL Server中的命名管道(named pipe)及其使用

    1. 什么是命名管道? 与TCP/IP(传输控制协议或internet协议)一样,命名管道是一种通讯协议.它一般用于局域网中,因为它要求客户端必须具有访问服务器资源的权限. 要解释这个问题,我还是摘录 ...

  3. Linux中的pipe(管道)与named pipe(FIFO 命名管道)

    catalogue 1. pipe匿名管道 2. named pipe(FIFO)有名管道 1. pipe匿名管道 管道是Linux中很重要的一种通信方式,是把一个程序的输出直接连接到另一个程序的输入 ...

  4. Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)

    整理自网络 Unix IPC包括:管道(pipe).命名管道(FIFO)与信号(Signal) 管道(pipe) 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道 ...

  5. 匿名管道(Pipe)和命名管道(FIFO)

    catalogue 1. pipe匿名管道 2. named pipe(FIFO)有名管道 1. pipe匿名管道 管道是Linux中很重要的一种通信方式,是把一个程序的输出直接连接到另一个程序的输入 ...

  6. c语言程序实现进程的管道通信,C 进程间通信--命名管道通信代码实现及其原理图示...

    在将这个题目之前大家需要了解几个概念: 进程: 我们可以先看进程的定义:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础: ...

  7. 命名管道(FIFO)

    FIFO FIFO Concept 管道的一个不足之处是没有名字,因此,只能用于具有亲缘关系的进程间通信,在命名管道(named pipe或FIFO)提出后,该限制得到了克服. FIFO不同于管道之处 ...

  8. Linux 命名管道

    前文中笔者介绍了管道,本文接着介绍命名管道.文中演示所用环境为 Ubuntu 18.04 desktop. 命名管道(named pipe)又被称为先进先出队列(FIFO),是一种特殊的管道,存在于文 ...

  9. linux pipe 命名管道,linux 进程学习笔记-named pipe (FIFO)命名管道

    与"无名管道"不同的是,FIFO拥有一个名称来标志它,所谓的名称实际上就是一个路径,比如"/tmp/my_fifo",其对应到磁盘上的一个管道文件,如果我们用f ...

  10. 进程间通信 - 命名管道实现

    引子 好,到这里呢,就需要介绍实现进程间通信的第四种方式了, 也就是通过命名管道来实现,前面介绍的那三种方式呢,都是有缺陷或者说局限性太强, 而这里介绍的命名管道相对来说,在这方面就做得好很多了, 比 ...

最新文章

  1. 大白话系列之C#委托与事件讲解(一)
  2. listen()与accept()函数的区别
  3. list排序方法python_python list 排序的两种方法及实例讲解
  4. python编程菱形_Python打印“菱形”星号代码方法
  5. ggmusic java证书过期_证书过期时的Java trustmanager行为
  6. 虚拟机克隆后如何修复网络、主机名等问题
  7. c语言报刊杂志订阅系统,中国报刊杂志大全_报刊大全_报刊杂志订阅
  8. .NET面试基础知识
  9. strcmp函数用法
  10. php派车系统,公务用车管理系统
  11. donet 微服务开发 学习-AOP框架基础
  12. 微信小程序-样式-引入
  13. Latex常用数学公式整理——导数
  14. 怎么下载Windows图片和传真查看器
  15. 【OpenGL开发】关于GLEW扩展库
  16. P语言: 为异步、容错和不确定性而生的编程语言
  17. 小程序商城制作一个需要多少钱?一般包括哪些费用?
  18. 按键精灵通过句柄获取窗口坐标_大漠插件后台找图、自动获取坐标窗口句柄鼠标多点左单击脚本...
  19. Python中的迭代器,生成器(yield语句),正则表达式,re模块
  20. c语言编译器2017,2016-2017年本科C语言编译器设计与实现毕业论文设计.doc

热门文章

  1. ARCGIS前端--读取excel数据并在地图上显示
  2. 大模型:深度学习领域的“巨无霸”
  3. 菜鸡的MVP架构漫谈
  4. 如何使用PathFileExists
  5. vue-treeselect只能选择叶子节点,不能选中父节点
  6. 移动端rem布局实例
  7. 计算机引领未来的趋势,笔记本的发展趋势 轻薄引领未来
  8. python编程<六>
  9. 部分GIS开源项目列表
  10. 学习记录——brats数据处理