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
名称的管道名称部分可以包含除反斜杠以外的任何字符,包括数字和特殊字符。 整个管道名称字符串最多可以包含 256 个字符。 管道名称不区分大小写。
[in] dwOpenMode
打开模式。
如果 dwOpenMode 指定除 0 以外的任何内容或下表中列出的标志,该函数将失败。
此参数必须指定以下管道访问模式之一。 必须为管道的每个实例指定相同的模式。
模式 | 意义 |
---|---|
|
管道是双向的;服务器和客户端进程都可以从管道读取和写入。 此模式为服务器提供对管道的等效 GENERIC_READ 和 GENERIC_WRITE 访问权限。 当客户端使用 CreateFile 函数连接到管道时,客户端可以指定 GENERIC_READ 或 GENERIC_WRITE或两者。 |
|
管道中的数据流仅从客户端到服务器。 此模式为服务器提供对管道 GENERIC_READ 访问权限的等效项。 连接到管道时,客户端必须指定 GENERIC_WRITE 访问权限。 如果客户端必须通过调用 GetNamedPipeInfo 或 GetNamedPipeHandleState 函数来读取管道设置,客户端必须在连接到管道时指定 GENERIC_WRITE 和 FILE_READ_ATTRIBUTES 访问。 |
|
管道中的数据流仅从服务器到客户端。 此模式为服务器提供对管道 GENERIC_WRITE 访问权限的等效项。 连接到管道时,客户端必须指定 GENERIC_READ 访问权限。 如果客户端必须通过调用 SetNamedPipeHandleState 函数来更改管道设置,客户端必须在连接到管道时指定 GENERIC_READ 和 FILE_WRITE_ATTRIBUTES 访问。 |
此参数还可以包括以下一个或多个标志,这些标志启用写通模式和重叠模式。 对于同一管道的不同实例,这些模式可能有所不同。
模式 | 意义 |
---|---|
|
如果尝试使用此标志创建管道的多个实例,则创建第一个实例会成功,但创建下一个实例失败,ERROR_ACCESS_DENIED。 |
|
已启用写通模式。 此模式仅影响字节类型管道上的写入操作,然后,仅当客户端和服务器进程位于不同的计算机上时。 如果启用此模式,则在写入到命名管道的数据通过网络传输并且位于远程计算机上的管道缓冲区中之前,写入命名管道的函数不会返回。 如果未启用此模式,系统将通过缓冲数据来提高网络操作的效率,直到最少的字节数累积或最长时间为止。 |
|
已启用重叠模式。 如果启用此模式,执行读取、写入和连接操作的函数可能需要花费大量时间才能立即返回。 此模式使启动操作的线程能够在后台执行耗时的操作时执行其他操作。 例如,在重叠模式下,线程可以处理管道多个实例上的同时输入和输出(I/O)操作,或者在同一管道句柄上执行同时读取和写入操作。 如果未启用重叠模式,则在完成操作之前,在管道句柄上执行读取、写入和连接操作的函数不会返回。 ReadFileEx 和 WriteFileEx 函数只能与管道句柄在重叠模式下使用。 ReadFile、WriteFile、ConnectNamedPipe,以及 TransactNamedPipe 函数可以同步或作为重叠操作执行。 |
此参数可以包括以下安全访问模式的任意组合。 对于同一管道的不同实例,这些模式可能有所不同。
模式 | 意义 |
---|---|
|
调用方将对命名管道的任意访问控制列表(ACL)具有写入访问权限。 |
|
调用方将具有对命名管道所有者的写入访问权限。 |
|
调用方将对命名管道的 SACL 具有写入访问权限。 有关详细信息,请参阅 Access-Control 列表(ACL) 和 SACL 访问权限。 |
[in] dwPipeMode
管道模式。
如果 dwPipeMode 指定除 0 以外的任何内容或下表中列出的标志,该函数将失败。
可以指定以下类型模式之一。 必须为管道的每个实例指定相同的类型模式。
模式 | 意义 |
---|---|
|
数据以字节流的形式写入管道。 此模式不能用于PIPE_READMODE_MESSAGE。 管道不会区分在不同写入操作期间写入的字节。 |
|
数据作为消息流写入管道。 管道将每次写入操作期间写入的字节视为消息单元。 GetLastError 函数在未完全读取消息时返回 ERROR_MORE_DATA。 此模式可用于 PIPE_READMODE_MESSAGE 或 PIPE_READMODE_BYTE。 |
可以指定以下读取模式之一。 同一管道的不同实例可以指定不同的读取模式。
模式 | 意义 |
---|---|
|
数据作为字节流从管道中读取。 此模式可用于 PIPE_TYPE_MESSAGE 或 PIPE_TYPE_BYTE。 |
|
数据作为消息流从管道中读取。 仅当同时指定 PIPE_TYPE_MESSAGE 时,才能使用此模式。 |
可以指定以下等待模式之一。 同一管道的不同实例可以指定不同的等待模式。
模式 | 意义 |
---|---|
|
已启用阻止模式。 在 ReadFile、WriteFile或 ConnectNamedPipe 函数中指定管道句柄时,在有要读取的数据、写入所有数据或客户端连接之前,这些操作不会完成。 使用此模式可能意味着在某些情况下无限期等待客户端进程执行操作。 |
|
启用非阻止模式。 在此模式下,ReadFile、WriteFile,ConnectNamedPipe 始终会立即返回。
请注意,非阻止模式支持与 Microsoft LAN Manager 版本 2.0 兼容,不应用于实现与命名管道的异步 I/O。 有关异步管道 I/O 的详细信息,请参阅 同步和重叠输入和输出。 |
可以指定以下远程客户端模式之一。 同一管道的不同实例可以指定不同的远程客户端模式。
模式 | 意义 |
---|---|
|
可以根据管道的安全描述符接受和检查来自远程客户端的连接。 |
|
来自远程客户端的连接会自动被拒绝。 |
[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 帐户、管理员和创建者所有者授予完全控制权。 他们还授予“每个人”组成员和匿名帐户的读取访问权限。
返回值
如果函数成功,则返回值是命名管道实例的服务器端的句柄。
如果函数失败,则返回值 INVALID_HANDLE_VALUE。 若要获取扩展的错误信息,请调用 GetLastError。
言论
若要使用 CreateNamedPipe创建命名管道的实例,用户必须具有对命名管道对象的 FILE_CREATE_PIPE_INSTANCE 访问权限。 如果要创建新的命名管道,则安全属性参数中的访问控制列表(ACL)定义命名管道的任意访问控制。
命名管道的所有实例都必须指定相同的管道类型(字节类型或消息类型)、管道访问(双工、入站或出站)、实例计数和超时值。 如果使用不同的值,此函数将失败,GetLastError 返回 ERROR_ACCESS_DENIED。
客户端进程使用 CreateFile 或 CallNamedPipe 函数连接到命名管道。 命名管道的客户端以字节模式启动,即使服务器端处于消息模式也是如此。 为了避免收到数据时出现问题,请将客户端设置为消息模式。 若要更改管道模式,管道客户端必须打开具有 GENERIC_READ 和 FILE_WRITE_ATTRIBUTES 访问权限的只读管道。
管道服务器在管道客户端启动之前不应执行阻止读取操作。 否则,可能会发生争用情况。 初始化代码(如 C 运行时)通常需要锁定和检查继承的句柄时,通常会发生这种情况。
每次创建命名管道时,系统都会使用非分页池(内核使用的物理内存)创建入站和/或出站缓冲区。 可以创建的管道实例数(以及线程和进程等对象)受可用非分页池的限制。 每个读取或写入请求都需要缓冲区中的空间来读取或写入数据,以及内部数据结构的额外空间。
输入和输出缓冲区大小是咨询的。 为命名管道的每个端保留的实际缓冲区大小是系统默认值、系统最小值或最大值,或指定大小向上舍入到下一个分配边界。 指定的缓冲区大小应足够小,使进程不会耗尽非分页池,但足以容纳典型请求。
每当管道写入操作发生时,系统首先尝试对管道写入配额对内存收费。 如果剩余的管道写入配额足以满足请求,则写入操作将立即完成。 如果剩余的管道写入配额太小,无法满足请求,系统将尝试扩展缓冲区,以便使用为进程保留的非分页池来容纳数据。 写入操作将阻止数据从管道读取,以便释放额外的缓冲区配额。 因此,如果指定的缓冲区大小太小,系统将根据需要增大缓冲区,但缺点是操作将阻止。 如果操作重叠,则会阻止系统线程;否则,将阻止应用程序线程。
若要释放命名管道使用的资源,应用程序在不再需要句柄时应始终关闭句柄,这可以通过调用 CloseHandle 函数或与实例句柄关联的进程结束来完成。 请注意,命名管道的实例可能有多个与之关联的句柄。 关闭命名管道实例的最后一个句柄时,始终删除命名管道的实例。
Windows 10 版本 1709:管道仅在应用容器中受支持;例如,从一个 UWP 进程到另一个属于同一应用的 UWP 进程。 此外,命名管道必须使用管道名称的语法 \\.\pipe\LOCAL\
。
例子
有关示例,请参阅 多线程管道服务器。
要求
要求 | 价值 |
---|---|
最低支持的客户端 | Windows 2000 Professional [桌面应用 |UWP 应用] |
支持的最低服务器 | Windows 2000 Server [桌面应用 |UWP 应用] |
目标平台 | 窗户 |
标头 | winbase.h (包括 Windows.h) |
库 | Kernel32.lib |
DLL | Kernel32.dll |