如何正确等待 NtCreateFile/etc 完成?
how to properly wait for completion of NtCreateFile/etc?
我在我的应用程序中使用本机 NT API 来访问文件 (NtCreateFile/etc)。为了避免处理 STATUS_PENDING 我在打开相关文件时使用了 FILE_SYNCHRONOUS_IO_NONALERT 标志。因此,打开文件如下所示:
UNICODE_STRING fname = toNtUnicode(ntpath);
OBJECT_ATTRIBUTES oa;
InitializeObjectAttributes(&oa, &fname, 0, at.handle(), NULL);
HANDLE h;
IO_STATUS_BLOCK io_status;
NTSTATUS r = NtOpenFile(&h, GENERIC_READ|SYNCHRONIZE, &oa, &io_status,
FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT|FILE_DIRECTORY_FILE);
if (r != STATUS_SUCCESS)
...; // error handling
不幸的是,它会导致内核序列化给定句柄上的所有操作。 IE。如果我尝试并行执行多个读取(使用多个线程)——在任何时间点只会处理一个请求。
我可以摆脱序列化:
HANDLE h;
IO_STATUS_BLOCK io_status;
NTSTATUS r = NtOpenFile(&h, GENERIC_READ|SYNCHRONIZE, &oa, &io_status,
FILE_SHARE_READ, FILE_DIRECTORY_FILE);
if (r == STATUS_PENDING)
...; // what to do here???
但是我究竟应该如何等待完成 -- WaitForSingleObject()
在文件句柄上?据我所知,由于多种原因它可以更改为信号状态——有什么方法可以告诉我打开的文件(或目录)操作已完成?
同样,如果我提交多个读取(来自多个线程)——我如何判断哪一个(如果有)已完成?
NtOpenFile
是同步的api。它永远不会 return STATUS_PENDING
给你。即使驱动程序 return STATUS_PENDING
for IRP_MJ_CREATE
i/o 子系统将等待 IRP 完成
https://github.com/Zer0Mem0ry/ntoskrnl/blob/master/Io/iomgr/parse.c#L1404
所以你永远不需要在 NtOpenFile
之后检查 STATUS_PENDING
并且永远不需要等待(原则上我们不能在这里等待 - 我们还没有文件句柄 - 所以不能等待它或者将其绑定为 IOCP。我们不会为 NtOpenFile
)
传递任何事件或其他回调机制
我在我的应用程序中使用本机 NT API 来访问文件 (NtCreateFile/etc)。为了避免处理 STATUS_PENDING 我在打开相关文件时使用了 FILE_SYNCHRONOUS_IO_NONALERT 标志。因此,打开文件如下所示:
UNICODE_STRING fname = toNtUnicode(ntpath);
OBJECT_ATTRIBUTES oa;
InitializeObjectAttributes(&oa, &fname, 0, at.handle(), NULL);
HANDLE h;
IO_STATUS_BLOCK io_status;
NTSTATUS r = NtOpenFile(&h, GENERIC_READ|SYNCHRONIZE, &oa, &io_status,
FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT|FILE_DIRECTORY_FILE);
if (r != STATUS_SUCCESS)
...; // error handling
不幸的是,它会导致内核序列化给定句柄上的所有操作。 IE。如果我尝试并行执行多个读取(使用多个线程)——在任何时间点只会处理一个请求。
我可以摆脱序列化:
HANDLE h;
IO_STATUS_BLOCK io_status;
NTSTATUS r = NtOpenFile(&h, GENERIC_READ|SYNCHRONIZE, &oa, &io_status,
FILE_SHARE_READ, FILE_DIRECTORY_FILE);
if (r == STATUS_PENDING)
...; // what to do here???
但是我究竟应该如何等待完成 -- WaitForSingleObject()
在文件句柄上?据我所知,由于多种原因它可以更改为信号状态——有什么方法可以告诉我打开的文件(或目录)操作已完成?
同样,如果我提交多个读取(来自多个线程)——我如何判断哪一个(如果有)已完成?
NtOpenFile
是同步的api。它永远不会 return STATUS_PENDING
给你。即使驱动程序 return STATUS_PENDING
for IRP_MJ_CREATE
i/o 子系统将等待 IRP 完成
https://github.com/Zer0Mem0ry/ntoskrnl/blob/master/Io/iomgr/parse.c#L1404
所以你永远不需要在 NtOpenFile
之后检查 STATUS_PENDING
并且永远不需要等待(原则上我们不能在这里等待 - 我们还没有文件句柄 - 所以不能等待它或者将其绑定为 IOCP。我们不会为 NtOpenFile
)