SourceForge上的Systools库包含一个类,它基本上是内存映射文件视图的包装器。我在其构造函数中有一些关于其代码的特定行的查询(在此q的底部完整显示),即
FMapObj := CreateFileMapping(THandle($FFFFFFFF), nil, RO3,
FMaxHi, FMaxLo, 'STMMFILE1');
如果构造函数的SharedData参数为True,则调用。请注意,如果SharedData是 是的,FileName参数被忽略,名称' STMMFILE1'而是用来代替。
这些是我的疑问:
首先,没有使用名称' STMMFILE1',Systools OLH所指的是"内部名称",表示运行的所有TStMemoryMappedFile实例系统使用相同的内存映射文件,以便两对需要独立MMF的应用程序无法使用TStMemoryMappedFile?换句话说,如果我使用它在应用程序A和A之间共享数据。 B,我无法在同一台机器上使用它在应用程序之间共享数据C& D与A& A不同。 B的共享数据。
其次,http://msdn.microsoft.com/en-gb/library/windows/desktop/aa366537%28v=vs.85%29.aspx处的MSDN文档指出:
"The remainder of the name can contain any character except the backslash character (\)"
这让我想知道CreateFileMapping如何与远程文件一起使用。这是打开远程文件句柄并将其作为第一个参数传递给CreateFileMapping的问题吗?如果是这样,那似乎与TStMemoryMappedFile.Create根本不兼容使用" THandle($ FFFFFFFF)",不会吗?
Systools TStMemoryMappedFile构造函数:
constructor TStMemoryMappedFile.Create(const FileName : string; {!!.02}
MaxSize : Cardinal;
ReadOnly : Boolean;
SharedData : Boolean);
var
RO1,
RO2,
RO3,
RO4,
FHi : DWORD;
SetSize: Boolean;
begin
inherited Create;
FMutex := CreateMutex(nil, False, nil);
FSharedData := SharedData;
if (FSharedData) then
FHeaderSize := SizeOf(Word) + SizeOf(Cardinal)
else
FHeaderSize := 0;
FReadOnly := ReadOnly;
if (SharedData) then
FReadOnly := False;
if (FReadOnly) then begin
RO1 := GENERIC_READ;
RO2 := FILE_ATTRIBUTE_READONLY;
RO3 := PAGE_READONLY;
RO4 := FILE_MAP_READ;
FMaxHi := 0;
FMaxLo := 0;
end else begin
RO1 := GENERIC_READ or GENERIC_WRITE;
RO2 := FILE_ATTRIBUTE_NORMAL;
RO3 := PAGE_READWRITE;
RO4 := FILE_MAP_WRITE;
FMaxHi := 0;
FMaxLo := MaxSize;
end;
if (not SharedData) then begin
FHandle := CreateFile(PChar(FileName),
RO1,
FILE_SHARE_READ or FILE_SHARE_WRITE,
nil,
OPEN_ALWAYS,
RO2,
0);
if (FHandle = INVALID_HANDLE_VALUE) then
RaiseStError(EStMMFileError, stscCreateFileFailed);
{reset FMaxLo if file is read/write and less < FileSize}
{the result is that the file size cannot be changed but the contents can}
{still be modified}
FDataSize := GetFileSize(FHandle, @FHi);
if (FDataSize <> $FFFFFFFF) then begin
if (not ReadOnly) and (FDataSize > FMaxLo) then
FMaxLo := FDataSize;
end else begin
CloseHandle(FHandle);
RaiseStError(EStMMFileError, stscGetSizeFailed);
end;
end else
FDataSize := 0;
if (not SharedData) then begin
FMapObj := CreateFileMapping(FHandle, nil, RO3, FMaxHi, FMaxLo, nil);
SetSize := False;
end else begin
if (FMaxLo > (High(Cardinal) - FHeaderSize)) then
FMaxLo := High(Cardinal) - FHeaderSize
else
FMaxLo := FMaxLo + FHeaderSize;
FMapObj := CreateFileMapping(THandle($FFFFFFFF), nil, RO3,
FMaxHi, FMaxLo, 'STMMFILE1');
SetSize := (GetLastError = ERROR_ALREADY_EXISTS);
end;
if (FMapObj = INVALID_HANDLE_VALUE) then
RaiseStError(EStMMFileError, stscFileMappingFailed);
FBuffer := MapViewOfFile(FMapObj, RO4, 0, 0, FMaxLo);
if (not Assigned(FBuffer)) then
RaiseStError(EStMMFileError, stscCreateViewFailed);
if (SharedData) then begin
if (SetSize) then
Move(PByteArray(FBuffer)[SizeOf(Word)-1], FDataSize, SizeOf(Cardinal))
else begin
Move(FHeaderSize, PByteArray(FBuffer)[0], SizeOf(Word));
FDataSize := 0;
Move(FDataSize, PByteArray(FBuffer)[SizeOf(Word)-1], SizeOf(Cardinal));
end;
end;
{set position to beginning}
FPos := FHeaderSize;
端;
答案 0 :(得分:2)
行为会在SharedData
上切换。您描述的代码是共享案例。由swap支持,并通过命名的文件映射共享。您询问是否所有进程都共享相同的映射。是的,那就是SharedData
的全部想法。
当然,这种设计存在很大的缺陷。假设我创建了一对使用此组件共享的应用程序。你做同样的事情。在我的应用和您的应用出现在同一台计算机上之前,它一切正常。你可以想象下一步会发生什么。
您应该修改代码以允许类的使用者提供名称。
远程文件的问题与此无关,因为共享映射对象由交换文件支持。有关对象名称的文档链接与文件系统名称无关。这些是内核对象,位于内核对象命名空间下。对于远程文件,它们无法可靠地映射。