Форум: "WinAPI";
Текущий архив: 2003.07.21;
Скачать: [xml.tar.bz2];
ВнизНепонятное поведение MMF при использовании файла страничного обм. Найти похожие ветки
← →
Anna Samoilova (2003-05-20 10:34) [0]Здравствуйте, многоуважаемые.
У меня такой конфуз вчера случился: создаю именованный объект файлового отображения отображаю данные на АП своего процесса – всё прекрасно!
НО, когда пытаюсь получить доступ к этому именованному объекту из любого другого процесса или даже этого самого, то и OpenFileMapping и CreateFileMapping возвращают handle отличающийся от того, что вернула мне CreateFileMapping при первом создании, и соответственно MapViewOfFile возвращает либо 0 либо какой-то бред.
Причём, что характерно, если я в том же процессе, где я создала объект MMF выполняю UnmapViewOfFile() и CloseHandle() а затем снова пытаюсь из любого процесса получить доступ к уже “закрытому” MFF, то и OpenFileMapping и CreateFileMapping возвращает именно тот handle, то вернула CreateFileMapping при первом вызове (т.е. при первичном создании MMF). Парадокс какой-то! Или я что-то напутала вконец (хотя раньше без проблем обеспечивала таким же образом обмен данными между DLL, находящимися в разных АП, но ведь не важно откуда я создаю MMF – из DLL или exe-файла!)
Итак, код:
// поля данной структуру буду отображать в файл подкачки
type
PInputRec = ^TInputRec;
TInputRec = record
SMyStr: string [50];
ICount: Integer;
end;
const
MMFName: PChar = "MyMMF063"; // имя объекта файлового отображения
var
GlobalData: PInputRec;
MMFHandle: HWND; // указатель на объект файлового отображения
procedure OpenGlobalData();
begin
MMFHandle:= CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, SizeOf(TInputRec), MMFName);
if MMFHandle = 0 then
begin
MessageBox(0, PChar("Can""t create FileMapping"), PChar("My app"), 0);
Exit;
end
else
MessageBox(0, PChar(IntToStr(MMFHandle)), PChar(" My app "), 0);
GlobalData:= MapViewOfFile(MMFHandle, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(TInputRec));
if GlobalData = nil then
begin
CloseHandle(MMFHandle);
MessageBox(0, PChar("Can""t make MapViewOfFile"), PChar(" My app "), 0);
Exit;
end;
end;
procedure CloseGlobalData();
begin
UnmapViewOfFile(GlobalData);
CloseHandle(MMFHandle);
end;
procedure InpDataToMMF();
begin
OpenGlobalData();
GlobalData^.sMyStr:= "test_My_MMF!!!";
GlobalData^.iCount:= 5;
end;
Вот такие пироги!
Вопрос вдогонку: можно ли с помощью WM_COPYDATA передавать не только строки, но и записи? (всё равно ведь через MMF делается)
Спасибо!
procedure InpDataToMMF();
begin
OpenGlobalData();
GlobalData^.SMyStr:= "test_My_MMF!!!";
GlobalData^.Icount:= 5;
end;
Вот такие пироги!
Вопрос вдогонку: можно ли с помощью WM_COPYDATA передавать не только строки, но и записи? (всё равно ведь через MMF делается)
Спасибо!
← →
MBo (2003-05-20 10:53) [1]выглядит нормально. Handle того же объекта ядра в другом процессе будет отличаться. Если он не нулевой, то это никак не должно повлиять на MapView.
CreateFileMapping(..., PChar(MMFName)); не поможет?
>Вопрос вдогонку
Да.
← →
Anna Samoilova (2003-05-20 10:59) [2]>>MBo © (20.05.03 10:53):
CreateFileMapping(..., PChar(MMFName)); не поможет?
см. выше:
const
MMFName: PChar = "MyMMF063";
Вот и я не пойму в чём дело. Даже если handle будет другой в другом процессе, то ведь всё равно не работает как надо.
А почему, кстати, handle другой - объёкт системы же один на всех! Ведь, к примеру у окна handle всегда один и в каком бы процессе мы бы не сделали FindWindow(nil, "This window") мы получим один и тот же handle!
2. Спасибо.
← →
Anna Samoilova (2003-05-20 12:25) [3]Sorry за повторения в первом посте - bugs not dead ;)
← →
Игорь Шевченко (2003-05-20 12:26) [4]Program Files\Borland\Delphi\Demos\IPCDemos\*.*
← →
Anna Samoilova (2003-05-20 12:30) [5]>>Игорь Шевченко © (20.05.03 12:26):
У меня нет подобного примера.
Я в MSDN посмотрела - ничего особенного, у меня всё верно, вроде бы.
Если пример из Demos небольшой, не могли бы сюда его поместить, если, конечно, это не протеворечит политики данного форума?
← →
Игорь Шевченко (2003-05-20 12:51) [6]Anna Samoilova (20.05.03 12:30)
Пример большой. Напишите на whitefranz@hotmail.com - вышлю.
← →
VMcL (2003-05-20 12:53) [7]>Anna Samoilova (20.05.03 12:30)
Давай мыло, вышлю. У меня Delphi 6.
← →
Ihor Osov'yak (2003-05-20 12:56) [8]Тоже с первого взгляда все нормально.
Даю работающий пример, может поможет, сделан на основании упоминаемой выше демки:
THandledObject = class(TObject)
protected
FHandle: THandle;
public
destructor Destroy; override;
property Handle: THandle read FHandle;
end;
{ TSharedMem }
{ This class simplifies the process of creating a region of shared memory.
In Win32, this is accomplished by using the CreateFileMapping and
MapViewOfFile functions. }
TSharedMem = class (THandledObject)
private
FName: string;
FSize: Integer;
FCreated: Boolean;
FFileView: Pointer;
fAccessMutex:THandle;
public
constructor Create(const Name: string; Size: Integer;
pSecurity:PSecurityAttributes = nil);
destructor Destroy; override;
function Lock(aTimeOut:integer):boolean;
function UnLock:boolean;
property Name: string read FName;
property Size: Integer read FSize;
property Buffer: Pointer read FFileView;
property Created: Boolean read FCreated;
end;
{ TSharedMem }
{ THandledObject }
destructor THandledObject.Destroy;
begin
if FHandle <> 0 then begin
CloseHandle(FHandle);
FHandle := 0;
end;
end;
constructor TSharedMem.Create(const Name: string; Size: Integer;
pSecurity: PSecurityAttributes = nil);
var flLock:boolean;
begin
try
FName := Name;
FSize := Size;
fAccessMutex := CreateMutex(pSecurity, False, PChar(Name+".m"));
if fAccessMutex = 0 then abort;
flLock := Lock(100);
try
{ CreateFileMapping, when called with $FFFFFFFF for the hanlde value,
creates a region of shared memory }
FHandle := CreateFileMapping($FFFFFFFF, pSecurity, PAGE_READWRITE, 0,
Size, PChar(Name));
if FHandle = 0 then abort;
FCreated := GetLastError = 0;
{ We still need to map a pointer to the handle of the shared memory region }
FFileView := MapViewOfFile(FHandle, FILE_MAP_WRITE, 0, 0, Size);
if FFileView = nil then abort;
if FCreated and flLock then FillChar(FFileView^,Size,0);
finally
if flLock then UnLock;
end;
//if FCreated then
except
Error(Format("Error creating TSharedMemory %s (%d)", [Name, GetLastError]));
end;
end;
destructor TSharedMem.Destroy;
begin
if FFileView <> nil then
UnmapViewOfFile(FFileView);
if fAccessMutex <> 0 then CloseHandle(fAccessMutex);
inherited Destroy;
end;
function TSharedMem.Lock(aTimeOut: integer):boolean;
begin
Result := WaitForSingleObject(fAccessMutex, aTimeOut) = WAIT_OBJECT_0;
end;
function TSharedMem.UnLock:boolean;
begin
Result := ReleaseMutex(fAccessMutex);
end;
Как видишь, единственное различие - если отображение создается - то оно обнуляется, для случая открітия уже созданого - ничего не делаем. Плюс использования мьютекса для арбитража доступа..
Пример использования:
procedure OpenSharedObject(aCallBack:TIPCEventReceiverCallBack);
var
sd: TSecurityDescriptor;
sa: TSecurityAttributes;
lpsa: PSecurityAttributes;
begin
lpsa := nil;
if Win32Platform = VER_PLATFORM_WIN32_NT then
begin
ZeroMemory(@sd, SizeOf(sd));
ZeroMemory(@sa, SizeOf(sa));
// set security for NT platforms
InitializeSecurityDescriptor(@sd, 1);
SetSecurityDescriptorDacl(@sd, True, nil, False);
sa.nLength := SizeOf(TSecurityAttributes);
sa.bInheritHandle := True;
sa.lpSecurityDescriptor := @sd;
lpsa := @sa;
end;
sSharedMem := TSharedMem.Create(sharedDataSign,sizeof(TSharedData),lpsa);
sIPCSender := TIPCEventSender.Create(notifFromSrvToConf_EventSign,lpsa);
sIPCReceiver :=TIPCEventReceiver.Create(aCallBack,0,notifFromConfToSrv_EventSign);
end;
procedure CloseSharedObject;
begin
if assigned(sSharedMem) then sSharedMem.Free;
if assigned(sIPCSender) then sIPCSender.Free;
if assigned(sIPCReceiver) then sIPCReceiver.Free;
sSharedMem := nil;
sIPCSender := nil;
sIPCReceiver := nil;
end;
procedure TFormSetStoragePrm.AfterConstruction;
var pSD:PSharedData;
begin
inherited;
lbWarning.Caption := "";
if sSharedMem.Lock(50) then begin
pSD:= sSharedMem.Buffer;
with pSD^...
sSharedMem.Unlock;
end
end;
Зы - используй более творческие имена, чем "MyMMF063"
К примеру, чего-то на основании GUI -
sharedDataSign = "237752D9-33A5-4B1E-92F9-6D1FAC659896"; { This string used as
the base for names of system objects (events,mutex, FMM) that are using for IPC
between the Service and the Configurator (FileStorageManager.exe)
}
← →
VMcL (2003-05-20 13:04) [9]>Ihor Osov"yak © (20.05.03 12:56)
В смысле не "GUI", а "GUID" :)
← →
Ihor Osov'yak (2003-05-20 13:07) [10]2 VMcL © (20.05.03 13:04)
Ну да, сорри .. Ctrl_Shift_G ...
← →
MBo (2003-05-20 13:59) [11]> почему, кстати, handle другой - объект системы же один на всех
Так устроена система ради безопасности - одинаковые в каждом процессе дескрипторы позволили бы внедряться друг в друга. Отдельное ВАП (вирт. адресное пространство) каждого процесса тоже для повышения устойчивости системы.
← →
Anna Samoilova (2003-05-20 14:53) [12]Всем спасибо. Пример нашла.
А вам, народ, не очень ленностно мой вариант попробовать - у вас тот же эффект будет или нет - просто интерестно?
← →
nikkie (2003-05-20 15:28) [13]>у вас тот же эффект будет или нет
у меня (D6 + Win2k) твой код работает, значение хендла одно и то же в разных процессах.
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2003.07.21;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.008 c