[英]windows: is it possible to dump (direct) a text file into a named pipe
[英]Where on Windows a named pipe file is stored?
我正在创建一个命名管道文件,如下所示:
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);
}
函数存在正常,没有错误。但是我在系统中找不到物理文件“mypipe”。Windows API 是否将其保存到特定位置?在 Windows 7 64 位上运行
引自http://en.wikipedia.org/wiki/Named_pipe 。
与 Unix 不同,命名管道不能安装在普通文件系统中。 也不同于它们的 Unix 对应物,命名管道是易变的(在对它们的最后一个引用关闭后被删除)。 每个管道都放置在命名管道文件系统 (NPFS) 的根目录中,挂载在特殊路径 \\.\\pipe\\ 下(即,名为“foo”的管道的完整路径名称为 \\.\\pipe\\foo )。 流水线中使用的匿名管道实际上是具有随机名称的命名管道。
当您在 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 的符号链接)。
NPFS的DriverEntry
函数赋值DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = NpFsdCreateNamedPipe;
. NpFsdCreateNamedPipe
调用NpCreateNewNamedPipe
,它将使用数据队列设置文件对象和文件对象的 CCB(上下文控制块)( FileObject->FsContext2
)。
名称为PipeName
的文件对象通过\\\\.\\pipe\\PipeName
访问并转换为\\Device\\NamedPipe\\PipeName
。 文件对象指向 Npfs 创建的NamedPipe
设备对象, IoGetRelatedDeviceObject
将返回该对象,这意味着所有WriteFile
和ReadFile
操作都会产生一个 IRP,该 IRP 被发送到此设备对象的设备堆栈的顶部,并传递管道名称\\PipeName
。 这类似于如何\\??\\C:\\Windows
即\\Device\\HarddiskVolume1\\Windows
文件对象PDEVICE_OBJECT
指向Device\\HarddiskVolume1
设备对象,文件对象的文件名UNICODE_STRING
是\\Windows
。 如果查看文件对象,则可以通过获取设备对象名称并将其附加到开头来获取完整路径。 IoCallDriver
最终将在设备对象的拥有驱动程序上调用。 根据传递的 IRP 中的 IRP 主要代码, IoCallDriver
调用DO->DriverObject->MajorFunction[IRP_MJ_Write]
,即NpFsdWrite
或DO->DriverObject->MajorFunction[IRP_MJ_Read]
,即NpFsdRead
。 这些函数将写入和读取数据队列Ccb->DataQueue[FILE_PIPE_OUTBOUND]
和Ccb->DataQueue[FILE_PIPE_INBOUND]
,其中包含DataEntry
标头的双向链表的头部,其中DataEntry[0]
是标头和DataEntry[1]
是缓冲区。 如果您将命名管道作为服务器打开,则它从入站读取并写入出站。 客户端从出站读取并写入入站。
如果使用PIPE_TYPE_MESSAGE
,那么每次写入管道时,都会将另一个DataEntry
添加到链表的尾部(因为NpWriteDataQueue
将在 IRP 中返回IoStatus
STATUS_MORE_PROCESSING_REQUIRED
,调用函数会在调用NpAddDataQueueEntry
之前检查该NpAddDataQueueEntry
),并且每个当你阅读时,一个DataEntry
将从链表的头部移除( NpReadDataQueue
只会在!Peek
调用NpRemoveDataQueueEntry
)。 如果您没有阅读所有消息,您将收到错误消息。 如果您使用PIPE_TYPE_BYTE
,则仅使用当前的DataEntry
并且在您写入时不会删除任何DataEntry
。 简单地说, DataEntry
的ByteOffset
字段随着读取的字节数而增加,我真的不确定以字节模式写入是如何工作的。
DataEntries、CCB 和 FileObjects 分配在非分页池中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.