1

更新 - 已解决并回答,违规行已被注释掉

简要描述;简介

即使我将(GENERIC_WRITE 或 GENERIC_WRITE)用于 CreateFile,将 PAGE_READWRITE 用于 CreateFileMapping,我在将 CreateFile 与 CreateFileMapping 链接时遇到问题

详细说明

我正在使用 CreateFileMapping 在进程之间共享内存。假设我没有映射到物理文件,而是使用 INVALID_HANDLE_VALUE 作为 CreateFileMapping 的第一个参数,那么实际的机制工作正常。这很好,但是我想要实现的是创建此映射的主进程使用基于磁盘的文件,并定期将其刷新到驱动器,并在它关闭时自动保存数据。

代码如下...... (当我运行它时,我得到“错误 5:访问被拒绝”作为 ShowMessage)

const MaximumMapSize = 256 * 1024;
var virtualMemoryPath : string = '';

function getFileHandle(mapname : string; maxSize  : dword) :THandle;
var diskfilename : string;

  lpFileName: PChar;
  dwDesiredAccess: DWORD;
  dwShareMode: DWORD;
  lpSecurityAttributes: PSecurityAttributes;
  dwCreationDisposition : dword;
  dwFlagsAndAttributes: DWORD;
  hTemplateFile : THandle ;

  temp : pointer;
begin
    Result := INVALID_HANDLE_VALUE;
    if (maxSize <= MaximumMapSize) and (Length(virtualMemoryPath) > 0) then
    begin

            diskfilename := virtualMemoryPath+mapname+'.bin';

            if FileExists(diskfilename) then
               Sysutils.DeleteFile(diskfilename);

            lpFileName              := PChar(diskfilename);
            //dwDesiredAccess         := GENERIC_WRITE or GENERIC_WRITE;//<<<wrong
            dwDesiredAccess         := GENERIC_READ or GENERIC_WRITE;
            dwShareMode             := 0;//FILE_SHARE_READ or FILE_SHARE_WRITE;//<<wrong
            lpSecurityAttributes    := nil;
            dwCreationDisposition   := CREATE_ALWAYS;
            dwFlagsAndAttributes    := 0;
            hTemplateFile           := 0 ;


            Result := CreateFile(
                lpFileName,
                dwDesiredAccess,
                dwShareMode,
                lpSecurityAttributes,
                dwCreationDisposition,
                dwFlagsAndAttributes,
                hTemplateFile);

           if (Result <> INVALID_HANDLE_VALUE) then
           begin
             GetMem(temp,maxsize);
             ZeroMemory(temp,maxsize);
             FileWrite(result,temp^,maxSize);
             FreeMem (temp,maxsize);
             FlushFileBuffers(result);
             SetFilePointer(result,0,0,FILE_BEGIN);
           end;
    end;
end;

function createMap (mapname : string ; maxSize: dword; var hFile: THandle) : THandle;
var
    lpFileMappingAttributes: PSecurityAttributes;
    flProtect           : DWORD;
    dwMaximumSizeHigh   : DWORD;
    dwMaximumSizeLow    : DWORD;
    lpName              : PChar;

    LastError : dword;
begin

    Result := INVALID_HANDLE_VALUE;

    if (maxSize > MaximumMapSize) then
        exit;

     // create a disk the file or return INVALID_HANDLE_VALUE if settings have not defined a path to folder
     hFile     :=  getFileHandle(mapname,maxSize);

     lpFileMappingAttributes := nil;
     flProtect          := PAGE_READWRITE;
     dwMaximumSizeHigh  := 0;
     dwMaximumSizeLow   := maxSize;
     lpName := PChar(mapname);

     Result := CreateFileMapping(
        hfile,
        lpFileMappingAttributes,
        flProtect,
        dwMaximumSizeHigh,
        dwMaximumSizeLow,
        lpName);

     if (Result = 0) then
     begin

         if (not (hFile = INVALID_HANDLE_VALUE) ) then
            CloseHandle(hFile);

         hFile := 0;
         LastError := GetLastError();
         ShowMessage( Format('Error %d : %s',[LastError,SysErrorMessage(LastError)]) );

     end
     else
     begin

        ShowMessage(Format('Returing handle %d',[result]));
        if (hFile = INVALID_HANDLE_VALUE) then
            hFile := 0;

     end;

end;
4

2 回答 2

5
        dwDesiredAccess         := GENERIC_WRITE or GENERIC_WRITE;
        dwShareMode             := FILE_SHARE_READ or FILE_SHARE_WRITE;

这行不通。您将需要读取和写入权限。此外,创建视图需要操作系统确保它是唯一可以写入文件的视图。除了通过视图之外,没有其他机制可以检测到另一个进程写入文件,并确保这样的写入在内存中及时和同步地可见。特别是在多线程访问视图的情况下,同步更新是不可能实现的。

读取共享同样不明智,操作系统不保证何时从视图中更新文件。唯一的保证是它会在所有视图关闭时更新。这也意味着需要有秩序地关闭 Windows,您无法使其可靠地应对断电等事故。同样,读取需要通过视图完成,而不是文件。唯一合适的选择是不共享。

于 2013-04-15T14:23:03.353 回答
3

错误在这里:

GENERIC_WRITE or GENERIC_WRITE

你的意思是:

GENERIC_READ or GENERIC_WRITE

解决这个问题,您的文件映射就可以创建了。

我同意 Hans 的观点,即您不应该共享文件句柄。

于 2013-04-15T14:26:56.803 回答