2015-03-31 74 views
1

在Linux下,我的程序会做这样的事情:在Windows中删除打开的文件(创建一个匿名文件)?

  • 过程1打开一个文件(例如,通过将其映射到内存)。我们称这个文件为#1
  • 进程2取消链接该文件,并创建一个具有相同名称的新文件。我们称这个文件为#2。
  • 进程1继续处理文件#1。当它关闭时,它被删除(因为它没有链接)。进程1继续处理文件#1中的内容,并且不会看到文件#2中的内容。
  • 当两个进程退出时,文件#2仍保留在磁盘上。

我想在Windows中实现相同的语义。在阅读this question后,我认为FILE_SHARE_DELETE基本上做到了这一点。是否足够使用FILE_SHARE_DELETE打开文件,还是需要考虑更多内容?

上面的执行流程仅仅是一个例子,我知道还有其他方法可以解决Windows中的确切问题,但我想了解如何使这些代码在Windows和Linux之间移植。

编辑:澄清:使用情况是为不同的不相关文件重新使用文件名,但让现有进程保留其数据(例如,考虑配置文件的事务更新),并使文件匿名(未命名),但继续像使用匿名内存映射一样使用它。我再次通过其他方式知道这两种方式都可以在Windows上使用,但我试图找到一种跨平台移植的方式。

+0

不,这不是什么'FILE_SHARE_DELETE'。该文件在进程1关闭之前不会被删除,因此进程2将无法创建具有相同名称的新文件。 – 2015-03-31 23:09:40

+0

第二个进程应该能够重命名该文件,然后*删除它,然后创建一个具有相同名称的新文件。 (关于何时可以或不能重命名正在使用的文件的规则,我有点模糊,但我认为它会起作用。) – 2015-03-31 23:14:46

+0

我不明白你的第一个用例:你的例子与你的描述矛盾,因为不同版本的配置文件不是无关的。 (如果这些文件真的不相关,那么正确的和可移植的解决方案就是文件具有唯一的名称。)所描述的第二个用例在Windows上绝对不可能,因为没有这样的事情就像没有命名的文件一样。 – 2015-04-03 00:53:52

回答

1

您可以通过使用CreateFile,CreateFileMapping和MapViewOfFile调用的组合来实现此目的。 MapViewOfFile将为您提供由磁盘上的文件支持的文件的内存映射缓冲区。

来自不同进程的执行时,下面的代码,会写最后的关闭过程的进程ID文件在C:\ TEMP \ TEMP.TXT

int main() 
 
{ 
 
\t TCHAR szMsg[256]; 
 
\t HANDLE hMapFile; 
 
\t LPCTSTR pBuf; 
 

 
\t HANDLE hFile = CreateFileW(
 
\t \t L"C:\\Temp\\temp.txt", 
 
\t \t GENERIC_WRITE|GENERIC_READ, 
 
\t \t FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE, 
 
\t \t NULL, 
 
\t \t CREATE_ALWAYS, 
 
\t \t FILE_ATTRIBUTE_NORMAL,NULL); 
 

 

 
\t hMapFile = CreateFileMapping(
 
\t \t hFile, \t \t \t \t \t // Handle of file opened with rw access 
 
\t \t NULL,     // default security 
 
\t \t PAGE_READWRITE,   // read/write access 
 
\t \t 0,      // maximum object size (high-order DWORD) 
 
\t \t BUF_SIZE,    // maximum object size (low-order DWORD) 
 
\t \t szName);     // name of mapping object 
 

 
\t if (hMapFile == NULL) 
 
\t { 
 
\t \t printf("Could not create file mapping object (%d).\n", GetLastError()); 
 
\t \t return 1; 
 
\t } 
 
\t pBuf = (LPTSTR) MapViewOfFile(hMapFile, // handle to map object 
 
\t \t FILE_MAP_ALL_ACCESS, // read/write permission 
 
\t \t 0, 
 
\t \t 0, 
 
\t \t BUF_SIZE); 
 

 
\t if (pBuf == NULL) 
 
\t { 
 
\t \t printf("Could not map view of file (%d).\n", GetLastError()); 
 
\t \t CloseHandle(hMapFile); 
 
\t \t return 1; 
 
\t } 
 
\t 
 
\t wsprintfW(szMsg, L"This is process id %d", GetCurrentProcessId()); 
 
\t CopyMemory((PVOID)pBuf, szMsg, (wcslen(szMsg) * sizeof(TCHAR))); 
 

 
\t MessageBoxW(NULL, szMsg, L"Check", MB_OK); 
 

 
\t UnmapViewOfFile(pBuf); 
 
\t CloseHandle(hMapFile); 
 
\t CloseHandle(hFile); 
 
\t return 0; 
 

 

 
}

确保在打开该文件具有GENERIC_READ | GENERIC_WRITE访问权限并允许FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE访问后续打开。

另请注意,在CreateFile中使用CREATE_ALWAYS会删除旧文件并每次调用CreateFile时都会打开一个新文件。这是你谈论的“取消关联”效应。

代码灵感来自Creating Named Shared Memory at msdn

+0

谢谢!是否存在使用内存映射的特定原因,或者普通的流I/O如何工作?请注意,我不是在共享内存或数据后。 – Krumelur 2015-03-31 14:57:46

+0

这是行不通的。在第二次运行时,CreateFile将失败,因为它无法创建一个与现有名称相同的新文件。 – 2015-03-31 23:11:28

+0

@Krumelur,内存映射用于避免在可能在磁盘上更改的文件上执行流I/O。 Windows提供了内存映射文件,让每个进程都有自己的文件感知,而不用担心磁盘上的内容。 – ExceptionalHandler 2015-04-01 03:33:48

相关问题