2017-09-13 104 views
0

我在我的應用程序中使用本機NT API來訪問文件(NtCreateFile/etc)。爲了避免處理STATUS_PENDING,我在打開相關文件時使用FILE_SYNCHRONOUS_IO_NONALERT標誌。因此,打開文件如下所示:如何正確等待NtCreateFile/etc的完成?

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 

不幸的是,它導致內核序列化給定句柄上的所有操作。即如果我嘗試並行執行多個讀取(使用多個線程) - 只有一個請求將在任何時間點處理。

我能擺脫系列化:

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()對文件處理?據我所知,由於許多原因它可以改變爲信號狀態 - 是否有任何方法可以告訴我打開的文件(或dir)操作已完成?同樣,如果我提交多個讀取(來自多個線程) - 我怎麼知道哪一個(如果有的話)完成了?

回答

0

NtOpenFile是同步api。它永遠不會返回STATUS_PENDING給你。即使IRP_MJ_CREATE I/O子系統驅動器返回STATUS_PENDING將等待IRP完整

https://github.com/Zer0Mem0ry/ntoskrnl/blob/master/Io/iomgr/parse.c#L1404

,所以你永遠不需要NtOpenFile後檢查STATUS_PENDING永不需要等待(在原則上我們不能在這裏等着 - 。我們還沒有文件句柄 - 所以不能在它等待或結合說IOCP我們不傳遞任何事件或NtOpenFile另一個回調機制)

+0

奇怪......我發誓,我觀察到STATUS_UPDATE時打開目錄。我會再試一次。同時,關於其他操作 - 我是否應該等待該事件傳遞給NtReadFile?如果是,那麼我並不需要SYNCHRONIZE標誌,對吧? –

+0

NtClose()怎麼樣 - 它保證是同步的嗎?另外,我是否可以假定所有關於NtXXX函數的說法都同樣適用於相應的ZwXXX函數(如果在用戶模式下調用)? –

+0

@ C.M。 'ZwOpenFile'和'ZwClose'是**同步** api的設計。它**從不**返回'STATUS_PENDING'。 * Nt *和* Zw *函數 - 在用戶模式下是別名。這是相同的功能(兩個名稱指向相同的地址) – RbMm