[英]File operation error on windows network drives
最近我遇到了低級文件操作的問題(在舊的遺留代碼中)
fd = open(file, O_RDWR);
...
lseek(fd, 0L, SEEK_END);
write(fd, buffer, len);
...
lseek(fd, pos, SEEK_SET);
read(fd, buffer, len);
on Windows 10 (client), if the file is on a shared network drive provided by eg Windows Server 2012 or 2016. In case of Windows Server 2012 the SMB version of the connection is 3.02, for Windows Server 2016 it is 3.1.1.
錯誤不是每次或同時發生 position,有時 lseek() 的返回值表示錯誤,但大多數時候似乎 lseek() 沒有返回正確的 EOF position,或者 write() EOF 的操作在下一個 lseek() 之前沒有完成,這是一種同步/緩存問題。 還嘗試了 fsync(fd)(或 _commit(fd))、O_SYNC 和延遲,但似乎並不可靠。
使用 Windows 7 作為客戶端,它的工作方式就像在本地驅動器上工作了多年一樣。 此外,當我在 Linux 中安裝該驅動器時,它適用於 SMB 版本 2.1、3.02、3.1.1。
所以我的問題是,SMB 協議、網絡共享和 Windows 10 是否存在已知問題,從而影響 lseek() 等這些低級文件操作?
更新:
這是一個例子
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#define _O_CREAT O_CREAT
#define _O_RDWR O_RDWR
#define _S_IREAD S_IREAD
#define _S_IWRITE S_IWRITE
#define _open open
#define _write write
#define _lseek lseek
#define _close close
#endif
char file[] = "file.txt";
int main() {
int fd = 0;
int ret = 0;
int len = 0;
off_t pos = 0;
off_t last_eof = 0;
char buffer[] = "12345";
int buflen = 0;
int n = 0;
buflen = strlen(buffer);
//unlink(file);
fd = _open(file, _O_CREAT|_O_RDWR, _S_IREAD|_S_IWRITE);
if (fd == -1) { fprintf(stderr, "ERROR open\n"); exit(1); }
ret = _close(fd);
if (ret == -1) { fprintf(stderr, "ERROR close\n"); exit(1); }
for (n = 0; n < 10000; n++)
{
fd = _open(file, _O_RDWR, _S_IREAD|_S_IWRITE);
if (fd == -1) { fprintf(stderr, "ERROR open [%d]\n", n); exit(1); }
pos = _lseek(fd, 0, SEEK_END);
if (pos == -1) { fprintf(stderr, "ERROR lseek1 [%d] pos: %ld\n", n, pos); exit(1); }
if (last_eof > 0 && pos != last_eof) {
fprintf(stderr, "ERROR [%d] eof: %ld last_eof: %ld\n", n, pos, last_eof);
exit(1);
}
len = _write(fd, buffer, buflen);
if (len != buflen) { fprintf(stderr, "ERROR write [%d]\n", n); exit(1); }
pos = _lseek(fd, 0, SEEK_END);
if (pos == -1) { fprintf(stderr, "ERROR lseek2 [%d] pos: %ld\n", n, pos); exit(1); }
last_eof = pos;
ret = _close(fd);
if (ret == -1) { fprintf(stderr, "ERROR close [%d]\n", n); exit(1); }
if (last_eof != (n+1)*buflen) {
fprintf(stderr, "ERROR [%d] eof: %ld\n", n, last_eof);
exit(1);
}
}
fprintf(stdout, "[%d] EOF: %ld\n", n, last_eof);
return 0;
}
(運行前刪除file.txt
!)
用 Visual Studio 編譯,在 Windows 10 和網絡驅動器上執行,它碰巧以“eof-error”退出,例如
> seek5win.exe
ERROR [112] eof: 555 last_eof: 560
即文件以 eof/size 560 關閉,然后以 eof/size 555 重新打開。如果沒有其他進程訪問該文件,則完成而不會出錯。 但是,如果資源管理器或其他一些進程掃描目錄,則 lseek/eof-estimate 有時會關閉。 使用_sopen_s()
和不同的 sh_flags 沒有幫助。
在 ProcessMonitor 中它看起來像這樣(當 Explorer 和 sublime-text 發揮作用時):
08:41:10,3133 seek5win.exe QueryStandardInformationFile \\;LanmanRedirector\...\file.txt SUCCESS AllocationSize: 4.096, EndOfFile: 540, NumberOfLinks: 1, DeletePending: False, Directory: False
08:41:10,3191 seek5win.exe CloseFile \\;LanmanRedirector\...\file.txt SUCCESS
08:41:10,3192 seek5win.exe WriteFile \\;LanmanRedirector\...\file.txt SUCCESS Offset: 0, Length: 4.096, I/O Flags: Non-cached, Paging I/O, Synchronous Paging I/O, Priority: Normal
08:41:10,3347 seek5win.exe CreateFile \\;LanmanRedirector\...\file.txt SUCCESS Desired Access: Generic Read/Write, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, Write, AllocationSize: n/a, OpenResult: Opened
08:41:10,3460 seek5win.exe QueryDeviceInformationVolume \\;LanmanRedirector\...\file.txt SUCCESS DeviceType: Disk, Characteristics: Remote
08:41:10,3594 seek5win.exe QueryStandardInformationFile \\;LanmanRedirector\...\file.txt SUCCESS AllocationSize: 4.096, EndOfFile: 540, NumberOfLinks: 1, DeletePending: False, Directory: False
08:41:10,3643 seek5win.exe ReadFile \\;LanmanRedirector\...\file.txt SUCCESS Offset: 539, Length: 1, Priority: Normal
08:41:10,3644 seek5win.exe ReadFile \\;LanmanRedirector\...\file.txt SUCCESS Offset: 0, Length: 540, I/O Flags: Non-cached, Paging I/O, Priority: Normal
08:41:10,3754 seek5win.exe QueryStandardInformationFile \\;LanmanRedirector\...\file.txt SUCCESS AllocationSize: 4.096, EndOfFile: 540, NumberOfLinks: 1, DeletePending: False, Directory: False
08:41:10,3838 seek5win.exe WriteFile \\;LanmanRedirector\...\file.txt SUCCESS Offset: 540, Length: 5
08:41:10,4013 seek5win.exe QueryStandardInformationFile \\;LanmanRedirector\...\file.txt SUCCESS AllocationSize: 4.096, EndOfFile: 545, NumberOfLinks: 1, DeletePending: False, Directory: False
08:41:10,4101 seek5win.exe CloseFile \\;LanmanRedirector\...\file.txt SUCCESS
08:41:10,4102 seek5win.exe WriteFile \\;LanmanRedirector\...\file.txt SUCCESS Offset: 0, Length: 4.096, I/O Flags: Non-cached, Paging I/O, Synchronous Paging I/O, Priority: Normal
08:41:10,4363 seek5win.exe CreateFile \\;LanmanRedirector\...\file.txt SUCCESS Desired Access: Generic Read/Write, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, Write, AllocationSize: n/a, OpenResult: Opened
08:41:10,4537 seek5win.exe QueryDeviceInformationVolume \\;LanmanRedirector\...\file.txt SUCCESS DeviceType: Disk, Characteristics: Remote
08:41:10,4751 seek5win.exe QueryStandardInformationFile \\;LanmanRedirector\...\file.txt SUCCESS AllocationSize: 4.096, EndOfFile: 545, NumberOfLinks: 1, DeletePending: False, Directory: False
08:41:10,4870 seek5win.exe ReadFile \\;LanmanRedirector\...\file.txt SUCCESS Offset: 544, Length: 1, Priority: Normal
08:41:10,4870 seek5win.exe ReadFile \\;LanmanRedirector\...\file.txt SUCCESS Offset: 0, Length: 545, I/O Flags: Non-cached, Paging I/O, Priority: Normal
08:41:10,5171 seek5win.exe QueryStandardInformationFile \\;LanmanRedirector\...\file.txt SUCCESS AllocationSize: 4.096, EndOfFile: 545, NumberOfLinks: 1, DeletePending: False, Directory: False
08:41:10,5239 seek5win.exe WriteFile \\;LanmanRedirector\...\file.txt SUCCESS Offset: 545, Length: 5
08:41:10,5375 seek5win.exe QueryStandardInformationFile \\;LanmanRedirector\...\file.txt SUCCESS AllocationSize: 4.096, EndOfFile: 550, NumberOfLinks: 1, DeletePending: False, Directory: False
08:41:10,5475 seek5win.exe CloseFile \\;LanmanRedirector\...\file.txt SUCCESS
08:41:10,5476 seek5win.exe WriteFile \\;LanmanRedirector\...\file.txt SUCCESS Offset: 0, Length: 4.096, I/O Flags: Non-cached, Paging I/O, Synchronous Paging I/O, Priority: Normal
08:41:10,5646 seek5win.exe CreateFile \\;LanmanRedirector\...\file.txt SUCCESS Desired Access: Generic Read/Write, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, Write, AllocationSize: n/a, OpenResult: Opened
08:41:10,5957 seek5win.exe QueryDeviceInformationVolume \\;LanmanRedirector\...\file.txt SUCCESS DeviceType: Disk, Characteristics: Remote
08:41:10,6111 seek5win.exe QueryStandardInformationFile \\;LanmanRedirector\...\file.txt SUCCESS AllocationSize: 4.096, EndOfFile: 550, NumberOfLinks: 1, DeletePending: False, Directory: False
08:41:10,6210 seek5win.exe ReadFile \\;LanmanRedirector\...\file.txt SUCCESS Offset: 549, Length: 1, Priority: Normal
08:41:10,6211 seek5win.exe ReadFile \\;LanmanRedirector\...\file.txt SUCCESS Offset: 0, Length: 550, I/O Flags: Non-cached, Paging I/O, Priority: Normal
08:41:10,6418 seek5win.exe QueryStandardInformationFile \\;LanmanRedirector\...\file.txt SUCCESS AllocationSize: 4.096, EndOfFile: 550, NumberOfLinks: 1, DeletePending: False, Directory: False
08:41:10,6501 seek5win.exe WriteFile \\;LanmanRedirector\...\file.txt SUCCESS Offset: 550, Length: 5
08:41:10,6547 Explorer.exe QueryDirectory \\;LanmanRedirector\...\file.txt SUCCESS Filter: file.txt, 1: file.txt
08:41:10,6715 seek5win.exe QueryStandardInformationFile \\;LanmanRedirector\...\file.txt SUCCESS AllocationSize: 4.096, EndOfFile: 555, NumberOfLinks: 1, DeletePending: False, Directory: False
08:41:10,6934 seek5win.exe CloseFile \\;LanmanRedirector\...\file.txt SUCCESS
08:41:10,6935 seek5win.exe WriteFile \\;LanmanRedirector\...\file.txt SUCCESS Offset: 0, Length: 4.096, I/O Flags: Non-cached, Paging I/O, Synchronous Paging I/O, Priority: Normal
08:41:10,6962 Explorer.exe CreateFile \\;LanmanRedirector\...\file.txt SUCCESS Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
08:41:10,7229 seek5win.exe CreateFile \\;LanmanRedirector\...\file.txt SUCCESS Desired Access: Generic Read/Write, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, Write, AllocationSize: n/a, OpenResult: Opened
08:41:10,7408 Explorer.exe QueryBasicInformationFile \\;LanmanRedirector\...\file.txt SUCCESS CreationTime: 31.10.2019 08:41:00, LastAccessTime: 31.10.2019 08:41:00, LastWriteTime: 31.10.2019 08:41:12, ChangeTime: 31.10.2019 08:41:12, FileAttributes: A
08:41:10,7456 seek5win.exe QueryDeviceInformationVolume \\;LanmanRedirector\...\file.txt SUCCESS DeviceType: Disk, Characteristics: Remote
08:41:10,7483 Explorer.exe CloseFile \\;LanmanRedirector\...\file.txt SUCCESS
08:41:10,7585 seek5win.exe QueryStandardInformationFile \\;LanmanRedirector\...\file.txt SUCCESS AllocationSize: 4.096, EndOfFile: 555, NumberOfLinks: 1, DeletePending: False, Directory: False
08:41:10,7645 seek5win.exe ReadFile \\;LanmanRedirector\...\file.txt SUCCESS Offset: 554, Length: 1, Priority: Normal
08:41:10,7646 seek5win.exe ReadFile \\;LanmanRedirector\...\file.txt SUCCESS Offset: 0, Length: 555, I/O Flags: Non-cached, Paging I/O, Priority: Normal
08:41:10,7886 seek5win.exe QueryStandardInformationFile \\;LanmanRedirector\...\file.txt SUCCESS AllocationSize: 4.096, EndOfFile: 555, NumberOfLinks: 1, DeletePending: False, Directory: False
08:41:10,8013 seek5win.exe WriteFile \\;LanmanRedirector\...\file.txt SUCCESS Offset: 555, Length: 5
08:41:10,8221 seek5win.exe QueryStandardInformationFile \\;LanmanRedirector\...\file.txt SUCCESS AllocationSize: 4.096, EndOfFile: 560, NumberOfLinks: 1, DeletePending: False, Directory: False
08:41:10,8246 sublime_.exe CreateFile \\;LanmanRedirector\...\file.txt SUCCESS Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
08:41:10,8319 seek5win.exe CloseFile \\;LanmanRedirector\...\file.txt SUCCESS
08:41:10,8319 seek5win.exe WriteFile \\;LanmanRedirector\...\file.txt SUCCESS Offset: 0, Length: 4.096, I/O Flags: Non-cached, Paging I/O, Synchronous Paging I/O, Priority: Normal
08:41:10,8453 seek5win.exe CreateFile \\;LanmanRedirector\...\file.txt SUCCESS Desired Access: Generic Read/Write, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, Write, AllocationSize: n/a, OpenResult: Opened
08:41:10,8477 sublime_.exe QueryBasicInformationFile \\;LanmanRedirector\...\file.txt SUCCESS CreationTime: 31.10.2019 08:41:00, LastAccessTime: 31.10.2019 08:41:00, LastWriteTime: 31.10.2019 08:41:12, ChangeTime: 31.10.2019 08:41:12, FileAttributes: A
08:41:10,8679 seek5win.exe QueryDeviceInformationVolume \\;LanmanRedirector\...\file.txt SUCCESS DeviceType: Disk, Characteristics: Remote
08:41:10,8690 sublime_.exe CloseFile \\;LanmanRedirector\...\file.txt SUCCESS
08:41:10,8843 seek5win.exe QueryStandardInformationFile \\;LanmanRedirector\...\file.txt SUCCESS AllocationSize: 4.096, EndOfFile: 555, NumberOfLinks: 1, DeletePending: False, Directory: False
08:41:10,8918 sublime_.exe CreateFile \\;LanmanRedirector\...\file.txt SUCCESS Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
08:41:10,8925 seek5win.exe ReadFile \\;LanmanRedirector\...\file.txt SUCCESS Offset: 554, Length: 1, Priority: Normal
08:41:10,9146 sublime_.exe QueryBasicInformationFile \\;LanmanRedirector\...\file.txt SUCCESS CreationTime: 31.10.2019 08:41:00, LastAccessTime: 31.10.2019 08:41:00, LastWriteTime: 31.10.2019 08:41:12, ChangeTime: 31.10.2019 08:41:12, FileAttributes: A
08:41:10,9167 seek5win.exe QueryStandardInformationFile \\;LanmanRedirector\...\file.txt SUCCESS AllocationSize: 4.096, EndOfFile: 555, NumberOfLinks: 1, DeletePending: False, Directory: False
08:41:10,9324 sublime_.exe CloseFile \\;LanmanRedirector\...\file.txt SUCCESS
08:41:10,9485 seek5win.exe CloseFile \\;LanmanRedirector\...\file.txt SUCCESS
它發生在 smb 版本 3.02 和 2.1 上。
在本地驅動器上,我從未觀察到這一點。 在 Windows 7 上,它在網絡驅動器上無錯誤地運行循環(掃描文件的其他進程可能使其非常慢)。 在 Linux 上,它也適用於網絡驅動器(mount -t cifs..)。
(部分答案和更多細節;解決方法)
write() 操作更新文件中的當前偏移量。 如果 write() 從 eof 開始,則新的偏移量成為新的 eof。 另一個文件句柄可能有不同的偏移量,盡管文件大小和 eof 應該是相同的(“全局”信息)。 因此,如果在為在 eof 處寫入的句柄更新當前偏移量之后更新 eof,並且如果操作系統(或某些驅動程序)沒有采取進一步的預防措施,則可能會發生lseek(fd, 0, SEEK_CUR)
並且lseek(fd, 0, SEEK_END)
返回不同的位置。
這是上面示例的更新,它在 Windows 10 和網絡驅動器上顯示了類似的內容。
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <io.h>
char file[] = "file.txt";
int main() {
int fd = 0;
int ret = 0;
int len = 0;
off_t pos = 0,
pos_eof = 0,
last_pos = 0,
last_eof = 0;
char buffer[] = "12345";
int buflen = 0;
int n = 0;
buflen = strlen(buffer);
//unlink(file);
fd = _open(file, _O_CREAT|_O_RDWR, _S_IREAD|_S_IWRITE);
ret = _close(fd);
for (n = 0; n < 10000; n++)
{
fd = _open(file, _O_RDWR, _S_IREAD|_S_IWRITE);
pos_eof = _lseek(fd, 0, SEEK_END);
if (last_eof > 0 && pos_eof != last_eof) {
fprintf(stderr, "ERROR [%d] eof: %ld last_eof: %ld\n", n, pos_eof, last_eof);
pos = _lseek(fd, 0, SEEK_CUR);
fprintf(stderr, "CUR pos: %ld\n", pos);
exit(1);
}
len = _write(fd, buffer, buflen);
pos = _lseek(fd, 0, SEEK_CUR);
pos_eof = _lseek(fd, 0, SEEK_END);
last_pos = pos;
last_eof = pos_eof;
ret = _close(fd);
if (last_pos != (n+1)*buflen) {
fprintf(stderr, "ERROR [%d] pos: %ld\n", n, last_pos);
//exit(1);
}
if (last_eof != (n+1)*buflen) {
fprintf(stderr, "ERROR [%d] eof: %ld (pos: %ld)\n", n, last_eof, last_pos);
//exit(1);
}
}
fprintf(stdout, "[%d] EOF: %ld\n", n, last_eof);
return 0;
}
由於我從未從文件操作中得到錯誤<0,因此沒有錯誤處理。 如果沒有其他進程接觸(讀取)該文件,則它運行時不會出錯。 如果有其他進程打開文件,我通常會得到這樣的 output:
ERROR [460] eof: 2295 last_eof: 2300
CUR pos: 2295
如果我用 windows CreateFile、WriteFile、SetFilePointer、...(版本(b))替換 io 函數,它運行得更快,但我仍然得到例如
ERROR [39] eof: 195 (pos: 200)
ERROR [40] eof: 200 last_eof: 195
CUR pos: 200
類似 posix 的調用(調用 CreateFile、WriteFile、...)需要更多時間,並且看起來文件在 eof 更新之前已關閉。 重新打開后最后 5 個字節消失了。
在 windows 版本 (b) 中,windows 調用顯示當前 position 和 eof 之間的差異,eof 不是最新的,當 SetFilePointer 被第二次調用時
pos = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); //_lseek(fd, 0, SEEK_CUR)
pos_eof = SetFilePointer(hFile, 0, NULL, FILE_END); //_lseek(fd, 0, SEEK_END);
但是關閉后文件大小就可以了。
編輯:也張貼在這里
更新:
如上面鏈接中所述,設置以下win10注冊表項可以規避問題(據我測試......):
HKLM\system\currentcontrolset\services\lanmanworkstation\parameters
FileInfoCacheLifetime REG_DWORD 0x0
FileNotFoundCacheLifetime REG_DWORD 0x0
DirectoryCacheLifetime REG_DWORD 0x0
看起來像 smb 協議的緩存參數,必須閱讀更多信息。 我相信默認值是不同的; 如果它在不設置這些值(為零)的情況下工作,那就太好了。
此處還描述了解決方法https://answers.microsoft.com/en-us/msoffice/forum/msoffice_access-mso_winother-msoversion_other/access-database-is-getting-corrupt-again-and-again/d3fcc0a2-7d35- 4a09-9269-c5d93ad0031d?messageId=c9ddd419-da56-42dd-a7ca-f93d29cf2c7f&page=13&auth=1 (Windows 10 中的租賃模式中的一個錯誤影響 Access 數據庫)
信息:
https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-7/ff686200(v=ws.10)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.