CreateNamedPipeA 函数 (winbase.h)

创建命名管道的实例,并返回后续管道操作的句柄。 命名管道服务器进程使用此函数创建特定命名管道的第一个实例并建立其基本属性,或创建现有命名管道的新实例。

语法

HANDLE CreateNamedPipeA(
  [in]           LPCSTR                lpName,
  [in]           DWORD                 dwOpenMode,
  [in]           DWORD                 dwPipeMode,
  [in]           DWORD                 nMaxInstances,
  [in]           DWORD                 nOutBufferSize,
  [in]           DWORD                 nInBufferSize,
  [in]           DWORD                 nDefaultTimeOut,
  [in, optional] LPSECURITY_ATTRIBUTES lpSecurityAttributes
);

参数

[in] lpName

唯一的管道名称。 此字符串必须具有以下形式:

\\.\pipe\pipename

名称的 pipename 部分可以包含反斜杠以外的任何字符,包括数字和特殊字符。 整个管道名称字符串的长度最多为 256 个字符。 管道名称不区分大小写。

[in] dwOpenMode

打开模式。

如果 dwOpenMode 指定除 0 以外的任何内容或下表中列出的标志,则函数将失败。

此参数必须指定以下管道访问模式之一。 必须为管道的每个实例指定相同的模式。

模型 含义
PIPE_ACCESS_DUPLEX
0x00000003
管道是双向的;服务器和客户端进程都可以从管道读取和写入管道。 此模式为服务器提供 对管道的等效GENERIC_READGENERIC_WRITE 访问权限。 当客户端使用 CreateFile 函数连接到管道时,可以指定GENERIC_READGENERIC_WRITE,或者同时指定这两者。
PIPE_ACCESS_INBOUND
0x00000001
管道中的数据流仅从客户端流向服务器。 此模式为服务器提供对管道 的等效GENERIC_READ 访问权限。 连接到管道时,客户端必须指定 GENERIC_WRITE 访问。 如果客户端必须通过调用 GetNamedPipeInfoGetNamedPipeHandleState 函数来读取管道设置,则客户端必须在连接到管道时指定 GENERIC_WRITEFILE_READ_ATTRIBUTES 访问。
PIPE_ACCESS_OUTBOUND
0x00000002
管道中的数据流仅从服务器流向客户端。 此模式为服务器提供等效于 GENERIC_WRITE 访问管道的权限。 连接到管道时,客户端必须指定 GENERIC_READ 访问。 如果客户端必须通过调用 SetNamedPipeHandleState 函数更改管道设置,则客户端必须在连接到管道时指定 GENERIC_READFILE_WRITE_ATTRIBUTES 访问。
 

此参数还可以包括以下一个或多个标志,这些标志启用写通模式和重叠模式。 对于同一管道的不同实例,这些模式可能不同。

模型 含义
FILE_FLAG_FIRST_PIPE_INSTANCE
0x00080000
如果尝试使用此标志创建管道的多个实例,则创建第一个实例会成功,但创建下一个实例会失败并 ERROR_ACCESS_DENIED
FILE_FLAG_WRITE_THROUGH
0x80000000
已启用写通模式。 此模式仅影响对字节类型管道的写入操作,并且仅当客户端和服务器进程位于不同计算机上时才影响写入操作。 如果启用此模式,则写入命名管道的函数不会返回,直到写入的数据通过网络传输并且位于远程计算机上的管道缓冲区中。 如果未启用此模式,系统会通过缓冲数据,直到最小字节数累积或最长时间结束,来提高网络操作的效率。
FILE_FLAG_OVERLAPPED
0x40000000
已启用重叠模式。 如果启用此模式,执行读取、写入和连接操作(可能需要很长时间才能完成)的函数会立即返回。 此模式使启动操作的线程能够在后台执行耗时操作时执行其他操作。 例如,在重叠模式下,线程可以处理同时输入和输出 (多个管道实例上的 I/O) 操作,或在同一管道句柄上同时执行读取和写入操作。 如果未启用重叠模式,则在操作完成之前,对管道句柄执行读取、写入和连接操作的函数不会返回。 ReadFileExWriteFileEx 函数只能与重叠模式下的管道句柄一起使用。 ReadFileWriteFileConnectNamedPipeTransactNamedPipe 函数可以同步执行,也可以作为重叠操作执行。
 

此参数可以包括以下安全访问模式的任意组合。 对于同一管道的不同实例,这些模式可能不同。

模型 含义
WRITE_DAC
0x00040000L
调用方将具有对命名管道的任意访问控制列表 (ACL) 的写入访问权限。
WRITE_OWNER
0x00080000L
调用方将具有对命名管道所有者的写入访问权限。
ACCESS_SYSTEM_SECURITY
0x01000000L
调用方将具有对命名管道的 SACL 的写入访问权限。 有关详细信息,请参阅访问控制Lists (ACL) SACL 访问权限

[in] dwPipeMode

管道模式。

如果 dwPipeMode 指定除 0 以外的任何内容或下表中列出的标志,则函数将失败。

可以指定以下类型模式之一。 必须为管道的每个实例指定相同的类型模式。

模型 含义
PIPE_TYPE_BYTE
0x00000000
数据作为字节流写入管道。 此模式不能与PIPE_READMODE_MESSAGE一起使用。 管道不区分在不同写入操作期间写入的字节。
PIPE_TYPE_MESSAGE
0x00000004
数据作为消息流写入管道。 管道将每次写入操作期间写入的字节视为消息单元。 GetLastError 函数在未完全读取消息时返回ERROR_MORE_DATA。 此模式可与 PIPE_READMODE_MESSAGEPIPE_READMODE_BYTE 一起使用。
 

可以指定以下读取模式之一。 同一管道的不同实例可以指定不同的读取模式。

模型 含义
PIPE_READMODE_BYTE
0x00000000
数据作为字节流从管道中读取。 此模式可用于 PIPE_TYPE_MESSAGEPIPE_TYPE_BYTE
PIPE_READMODE_MESSAGE
0x00000002
数据作为消息流从管道中读取。 仅当还指定 了PIPE_TYPE_MESSAGE 时,才能使用此模式。
 

可以指定以下等待模式之一。 同一管道的不同实例可以指定不同的等待模式。

模型 含义
PIPE_WAIT
0x00000000
阻止模式已启用。 在 ReadFileWriteFileConnectNamedPipe 函数中指定管道句柄时,在有要读取的数据、写入所有数据或连接客户端之前,操作不会完成。 在某些情况下,使用此模式可能意味着无限期等待客户端进程执行操作。
PIPE_NOWAIT
0x00000001
启用了非阻止模式。 在此模式下, ReadFileWriteFileConnectNamedPipe 始终立即返回。

请注意,支持非阻止模式以实现与 Microsoft LAN Manager 版本 2.0 的兼容性,并且不应用于通过命名管道实现异步 I/O。 有关异步管道 I/O 的详细信息,请参阅 同步和重叠输入和输出

 

可以指定以下远程客户端模式之一。 同一管道的不同实例可以指定不同的远程客户端模式。

模型 含义
PIPE_ACCEPT_REMOTE_CLIENTS
0x00000000
可以接受来自远程客户端的Connections,并对照管道的安全描述符进行检查。
PIPE_REJECT_REMOTE_CLIENTS
0x00000008
来自远程客户端的Connections将自动被拒绝。

[in] nMaxInstances

可为此管道创建的最大实例数。 管道的第一个实例可以指定此值;必须为管道的其他实例指定相同的数字。 可接受的值范围为 1 到 PIPE_UNLIMITED_INSTANCES (255) 。

如果 此参数PIPE_UNLIMITED_INSTANCES,则可以创建的管道实例数仅受系统资源的可用性限制。 如果 nMaxInstances 大于 PIPE_UNLIMITED_INSTANCES,则返回值为 INVALID_HANDLE_VALUE,GetLastError 返回ERROR_INVALID_PARAMETER

[in] nOutBufferSize

要为输出缓冲区保留的字节数。 有关调整命名管道缓冲区大小的讨论,请参阅以下“备注”部分。

[in] nInBufferSize

要为输入缓冲区保留的字节数。 有关调整命名管道缓冲区大小的讨论,请参阅以下“备注”部分。

[in] nDefaultTimeOut

如果 WaitNamedPipe 函数指定NMPWAIT_USE_DEFAULT_WAIT,则为默认超时值 (以毫秒为单位)。 命名管道的每个实例必须指定相同的值。

如果值为零,则默认超时为 50 毫秒。

[in, optional] lpSecurityAttributes

指向 SECURITY_ATTRIBUTES 结构的指针,该结构指定新的命名管道的安全描述符,并确定子进程是否可以继承返回的句柄。 如果 lpSecurityAttributesNULL,则命名管道将获取默认安全描述符,并且无法继承句柄。 命名管道的默认安全描述符中的 ACL 授予 LocalSystem 帐户、管理员和创建者所有者的完全控制权。 他们还向 Everyone 组的成员和匿名帐户授予读取访问权限。

返回值

如果函数成功,则返回值是命名管道实例的服务器端的句柄。

如果函数失败,则返回值为 INVALID_HANDLE_VALUE。 要获得更多的错误信息,请调用 GetLastError。

注解

若要使用 CreateNamedPipe 创建命名管道的实例,用户必须具有对命名管道对象的 FILE_CREATE_PIPE_INSTANCE 访问权限。 如果创建新的命名管道,则安全属性参数 (ACL) 的访问控制列表定义命名管道的任意访问控制。

命名管道的所有实例必须指定相同的管道类型 (字节类型或消息类型) 、管道访问 (双工、入站或出站) 、实例计数和超时值。 如果使用不同的值,此函数将失败, GetLastError 将返回 ERROR_ACCESS_DENIED

客户端进程使用 CreateFileCallNamedPipe 函数连接到命名管道。 命名管道的客户端以字节模式启动,即使服务器端处于消息模式也是如此。 为了避免在接收数据时出现问题,请将客户端设置为消息模式。 若要更改管道的模式,管道客户端必须打开具有 GENERIC_READ 的只读管道,并 FILE_WRITE_ATTRIBUTES 访问权限。

在管道客户端启动之前,管道服务器不应执行阻止读取操作。 否则,可能会出现争用情况。 当初始化代码(如 C 运行时)需要锁定和检查继承的句柄时,通常会发生这种情况。

每次创建命名管道时,系统都会使用非分页池(内核使用的物理内存)创建入站和/或出站缓冲区。 可以创建的管道实例 (以及对象(如线程和进程) )的数量受可用非分页池的限制。 每个读取或写入请求都需要缓冲区中用于读取或写入数据的空间,以及用于内部数据结构的额外空间。

输入和输出缓冲区大小为公告。 为命名管道的每一端保留的实际缓冲区大小为系统默认值、系统最小值或最大值,或向上舍入到下一个分配边界的指定大小。 指定的缓冲区大小应足够小,以便进程不会耗尽非分页池,但要足够大,足以容纳典型请求。

每当发生管道写入操作时,系统首先会尝试根据管道写入配额为内存充电。 如果剩余的管道写入配额足以满足请求,则写入操作将立即完成。 如果剩余的管道写入配额太小而无法满足请求,系统将尝试使用为进程保留的非分页池来扩展缓冲区以容纳数据。 写入操作将阻塞,直到从管道读取数据,以便释放额外的缓冲区配额。 因此,如果指定的缓冲区大小太小,系统将根据需要增大缓冲区,但缺点是操作会阻塞。 如果操作重叠,则会阻止系统线程;否则,应用程序线程将被阻止。

若要释放命名管道使用的资源,应用程序应始终在不再需要句柄时关闭句柄,这可以通过调用 CloseHandle 函数或在与实例句柄关联的进程结束时完成。 请注意,命名管道的实例可能有多个与之关联的句柄。 关闭命名管道实例的最后一个句柄时,始终会删除命名管道的实例。

Windows 10版本 1709:管道仅在应用容器中受支持;即,从一个 UWP 进程到另一个属于同一应用的 UWP 进程。 此外,命名管道必须使用语法 \\.\pipe\LOCAL\ 来表示管道名称。

示例

有关示例,请参阅 多线程管道服务器

要求

要求
最低受支持的客户端 Windows 2000 专业版 [桌面应用 |UWP 应用]
最低受支持的服务器 Windows 2000 Server [桌面应用 |UWP 应用]
目标平台 Windows
标头 winbase.h (包括 Windows.h)
Library Kernel32.lib
DLL Kernel32.dll

另请参阅

ConnectNamedPipe

CreateFile

管道函数

管道概述

ReadFile

ReadFileEx

SECURITY_ATTRIBUTES

TransactNamedPipe

WaitNamedPipe

WriteFile

WriteFileEx