Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.07.21;
Скачать: CL | DM;

Вниз

Непонятное поведение 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 вся ветка

Текущий архив: 2003.07.21;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.019 c
14-68013
Фикус
2003-07-04 08:16
2003.07.21
Интересно, а кто был 20000000 посетителем? :)


7-68077
Vicheslav
2003-05-04 15:32
2003.07.21
Flash Drive USB Win2K как ним работать?


1-67873
Hack_Man
2003-07-08 09:49
2003.07.21
Как скрыть форму, но что бы был виден Image


6-67946
Fixxxer
2003-05-12 00:37
2003.07.21
Socket


14-68006
DenKop
2003-07-03 19:36
2003.07.21
vba office