[英]Where on Windows a named pipe file is stored?
I am creating a named pipe file as follows:我正在创建一个命名管道文件,如下所示:
void SavePipeFile(){
HANDLE hpipe;
BOOL bRet;
DWORD size;
hpipe =
CreateNamedPipe(
L"\\\\.\\pipe\\mypipe",
PIPE_ACCESS_OUTBOUND,
PIPE_TYPE_BYTE,
1,
0,
0,
0,
NULL
);
if(hpipe == NULL || hpipe==INVALID_HANDLE_VALUE)
{
printf("Error opening handle\n");
}
CloseHandle(hpipe);
}
The function exists ok,no errors.But I can't find the physical file "mypipe" in the system.Does Windows API saves it to a specific location?Running on Windows 7 64bit函数存在正常,没有错误。但是我在系统中找不到物理文件“mypipe”。Windows API 是否将其保存到特定位置?在 Windows 7 64 位上运行
Quote from http://en.wikipedia.org/wiki/Named_pipe .引自http://en.wikipedia.org/wiki/Named_pipe 。
Named pipes cannot be mounted within a normal filesystem, unlike in Unix.
与 Unix 不同,命名管道不能安装在普通文件系统中。 Also unlike their Unix counterparts, named pipes are volatile (removed after the last reference to them is closed).
也不同于它们的 Unix 对应物,命名管道是易变的(在对它们的最后一个引用关闭后被删除)。 Every pipe is placed in the root directory of the named pipe filesystem (NPFS), mounted under the special path \\.\\pipe\\ (that is, a pipe named "foo" would have a full path name of \\.\\pipe\\foo).
每个管道都放置在命名管道文件系统 (NPFS) 的根目录中,挂载在特殊路径 \\.\\pipe\\ 下(即,名为“foo”的管道的完整路径名称为 \\.\\pipe\\foo )。 Anonymous pipes used in pipelining are actually named pipes with a random name.
流水线中使用的匿名管道实际上是具有随机名称的命名管道。
When you create a named pipe on ReactOS, CreateNamedPipe
in kernel32.dll calls NtCreateNamedPipeFile
in ntdll.dll, which performs a syscall + index into SSDT to its kernel mode counterpart in ntoskrnl.exe, which calls IoCreateFile
, which calls IopCreateFile
, which will call ObOpenObjectByName
, which calls ObpLookupObjectName
, which calls the object parse routine ParseRoutine = ObjectHeader->Type->TypeInfo.ParseProcedure
, which will be IopParseRoutine
, which sends an IRP with major code IRP_MJ_CREATE_NAMED_PIPE to the NPFS driver, which it acquires by its name \\Device\\NamedPipe
(it will parse \\\\.\\pipe
as \\??\\pipe
, which is a symbolic link to the \\Device\\NamedPipe
DO created by the NPFS driver).当您在 ReactOS 上创建命名管道时,kernel32.dll 中的
CreateNamedPipe
调用 ntdll.dll 中的NtCreateNamedPipeFile
,后者执行系统调用 + SSDT 索引到 ntoskrnl.exe 中的内核模式对应项,后者调用IoCreateFile
,后者调用IopCreateFile
,后者将调用ObOpenObjectByName
,它调用ObpLookupObjectName
,该调用对象的解析例程ParseRoutine = ObjectHeader->Type->TypeInfo.ParseProcedure
,这将是IopParseRoutine
,它发送一个IRP与主代码IRP_MJ_CREATE_NAMED_PIPE到NPFS驱动器,其获取由它的名字\\Device\\NamedPipe
(它将\\\\.\\pipe
解析为\\??\\pipe
,这是到由 NPFS 驱动程序创建的\\Device\\NamedPipe
DO 的符号链接)。
The DriverEntry
function of the NPFS assigns DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = NpFsdCreateNamedPipe;
NPFS的
DriverEntry
函数赋值DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = NpFsdCreateNamedPipe;
. .
NpFsdCreateNamedPipe
calls NpCreateNewNamedPipe
, which will set up the file object and the CCB (Context Control Block) ( FileObject->FsContext2
) of the file object with the data queues. NpFsdCreateNamedPipe
调用NpCreateNewNamedPipe
,它将使用数据队列设置文件对象和文件对象的 CCB(上下文控制块)( FileObject->FsContext2
)。
The file object of name PipeName
is accessed via \\\\.\\pipe\\PipeName
and translates to \\Device\\NamedPipe\\PipeName
.名称为
PipeName
的文件对象通过\\\\.\\pipe\\PipeName
访问并转换为\\Device\\NamedPipe\\PipeName
。 The file object points to the NamedPipe
device object created by the Npfs, which IoGetRelatedDeviceObject
will return, meaning that all WriteFile
and ReadFile
operations result in an IRP, which gets sent to the top of the device stack of this Device Object, passing the pipe name \\PipeName
.文件对象指向 Npfs 创建的
NamedPipe
设备对象, IoGetRelatedDeviceObject
将返回该对象,这意味着所有WriteFile
和ReadFile
操作都会产生一个 IRP,该 IRP 被发送到此设备对象的设备堆栈的顶部,并传递管道名称\\PipeName
。 This is similar to how \\??\\C:\\Windows
ie \\Device\\HarddiskVolume1\\Windows
file object PDEVICE_OBJECT
points to the Device\\HarddiskVolume1
device object, the file name UNICODE_STRING
of the file object being \\Windows
.这类似于如何
\\??\\C:\\Windows
即\\Device\\HarddiskVolume1\\Windows
文件对象PDEVICE_OBJECT
指向Device\\HarddiskVolume1
设备对象,文件对象的文件名UNICODE_STRING
是\\Windows
。 If you look at the file object, you can get the full path by getting the device object name and appending it to the start.如果查看文件对象,则可以通过获取设备对象名称并将其附加到开头来获取完整路径。
IoCallDriver
will be eventually called on the owning driver of the device object. IoCallDriver
最终将在设备对象的拥有驱动程序上调用。 Based on the IRP major code in the IRP passed, IoCallDriver
calls either DO->DriverObject->MajorFunction[IRP_MJ_Write]
, which is NpFsdWrite
or DO->DriverObject->MajorFunction[IRP_MJ_Read]
, which is NpFsdRead
.根据传递的 IRP 中的 IRP 主要代码,
IoCallDriver
调用DO->DriverObject->MajorFunction[IRP_MJ_Write]
,即NpFsdWrite
或DO->DriverObject->MajorFunction[IRP_MJ_Read]
,即NpFsdRead
。 Those functions will write and read to the data queues Ccb->DataQueue[FILE_PIPE_OUTBOUND]
and Ccb->DataQueue[FILE_PIPE_INBOUND]
, which contain the head of a doubly linked list of DataEntry
headers where DataEntry[0]
is the header and DataEntry[1]
is the buffer.这些函数将写入和读取数据队列
Ccb->DataQueue[FILE_PIPE_OUTBOUND]
和Ccb->DataQueue[FILE_PIPE_INBOUND]
,其中包含DataEntry
标头的双向链表的头部,其中DataEntry[0]
是标头和DataEntry[1]
是缓冲区。 If you open the named pipe as a server then it reads from the inbound and writes to the outbound.如果您将命名管道作为服务器打开,则它从入站读取并写入出站。 The client reads from the outbound and writes to the inbound.
客户端从出站读取并写入入站。
If you use PIPE_TYPE_MESSAGE
, then every time you write to the pipe, another DataEntry
will be added to the tail of the linked list (because NpWriteDataQueue
will return with IoStatus
STATUS_MORE_PROCESSING_REQUIRED
in the IRP, which the calling function checks before calling NpAddDataQueueEntry
), and each time you read, a DataEntry
will be removed from the head of the linked list ( NpReadDataQueue
will only call NpRemoveDataQueueEntry
if !Peek
).如果使用
PIPE_TYPE_MESSAGE
,那么每次写入管道时,都会将另一个DataEntry
添加到链表的尾部(因为NpWriteDataQueue
将在 IRP 中返回IoStatus
STATUS_MORE_PROCESSING_REQUIRED
,调用函数会在调用NpAddDataQueueEntry
之前检查该NpAddDataQueueEntry
),并且每个当你阅读时,一个DataEntry
将从链表的头部移除( NpReadDataQueue
只会在!Peek
调用NpRemoveDataQueueEntry
)。 You will get an error if you do not read all of the message.如果您没有阅读所有消息,您将收到错误消息。 If you use
PIPE_TYPE_BYTE
, then only the current DataEntry
is used and no DataEntry
s are removed when you write.如果您使用
PIPE_TYPE_BYTE
,则仅使用当前的DataEntry
并且在您写入时不会删除任何DataEntry
。 Simply, the ByteOffset
field of the DataEntry
is increased by the number of bytes read, and I'm really not sure how writing in byte mode works.简单地说,
DataEntry
的ByteOffset
字段随着读取的字节数而增加,我真的不确定以字节模式写入是如何工作的。
DataEntries, CCBs and FileObjects are allocated on the non-paged pool. DataEntries、CCB 和 FileObjects 分配在非分页池中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.