Вниз
Скачать: CL | DM;

Гранулярность памяти, FileMapping   Найти похожие ветки 

 
dmk ©   (2004-03-25 00:37) [0]

1. Насколько я понял из MSDN, проекция файла в память
должна начинаться с адреса кратному размеру выделения
памяти(_system_info.dwAllocationGranularity) в моем случае
это 65536.
Так вот вопрос: Как получить блок памяти который начинается
с адреса памяти кратного этому размеру?
Или опровергните мои соображения если я не так понял.
В любом случае блок памяти выделенный с помощью функций
WinApi или Delphi начинается с адреса кратного 65536 + 4 байта! При этом функция MapViewOfFileEx ни в какую не хочет пронимать
в виде последнего параметра мой блок памяти и присваивает
ему nil.

2. Приведенная ниже процедура - это пример из книги Рихтера
"Windows для профессианалов". Она просто читает данные из файла и подсчитывает кол-во нулей. Я хотел сделать чтение файлов с
помощью проекции но в свой блок памяти. Возможно ли это сделать
непосредственно из файла минуя промежуточные, выделенные
системой блоки памяти?

3. Почему скорость проецирования получается ниже, нежели
если прочесть файл процедурой BlockRead?

procedure TMainForm.FmButtonClick(Sender: TObject);
var
 hName:                String;
 hFile:                THandle;
 hSize:                DWord;
 hOffset:              DWord;
 hMap:                 THandle;
 AMode:                DWord;
 lpBytes:              Pointer;
 sInfo:                _System_Info;
 dwBlockSize:          DWord;
 MappedBytes:          DWord;
 NumZeros:             DWord;
 sT,eT:                DWord;
 tB:                   Pointer;
 //i:                    DWord;

begin
 AMode := GENERIC_READ;

 If not OpenDialog.Execute then Exit;

 hName := OpenDialog.FileName;

 GetSystemInfo(sInfo);

 dwBlockSize := sInfo.dwAllocationGranularity;

 sT := GetTickCount;

 hFile := CreateFile(PChar(hName), AMODE,
                     0, nil, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);

 //...
 If hFile = INVALID_HANDLE_VALUE then
   begin
     ErrorMessage(hName + #13 + #13 + "File open error!");
     CloseHandle(hFile);
     Exit;
   end;

 hSize := GetFileSize(hFile, nil);
 If hSize < dwBlockSize then dwBlockSize := hSize;

  hMap := CreateFileMapping(hFile, nil, PAGE_READONLY, 0, hSize, "Test866");
 If (hMap <> 0) and (GetLastError = ERROR_ALREADY_EXISTS) then
   begin
     CloseHandle(hMap);
     hMap := 0;
   end;

  If hFile <> 0 then CloseHandle(hFile);

  MappedBytes := hSize;
 hOffset := 0;
 NumZeros := 0;

 tB := SysGetMem(dwBlockSize);

 While MappedBytes <> 0 do
   begin
     lpBytes := MapViewOfFileEx(hMap, FILE_MAP_READ, 0, hOffset, dwBlockSize, nil);

      asm
         push  ecx
         push  edx
         push  ebx

         mov   edx, DWord ptr [lpBytes]
         mov   ecx, dwBlockSize
         mov   ebx, NumZeros

       @@np:
         mov   al, [edx]
         test  al, al
         jnz   @@Ex
         inc   ebx
        @@Ex:
         inc   edx
         dec   ecx
         jnz   @@np

         mov   NumZeros, ebx

         pop   ebx
         pop   edx
         pop   ecx
     end;

     UnmapViewOfFile(lpBytes);

     Inc(hOffset, dwBlockSize);
     Dec(MappedBytes, dwBlockSize);

     If MappedBytes < dwBlockSize then
       dwBlockSize := MappedBytes;

  end;//While

  If hMap <> 0 then CloseHandle(hMap);

  eT := GetTickCount;

 SysFreeMem(tB);

 DrawTimeValue("Map time: ", sT, eT);

 InfoMessage("Num zeros: " + IntToStr(NumZeros));
end;


 
dmk ©   (2004-03-25 00:38) [1]

Извиняюсь! пронимать - понимать


 
Игорь Шевченко ©   (2004-03-25 01:14) [2]


> 3. Почему скорость проецирования получается ниже, нежели
> если прочесть файл процедурой BlockRead?


Кэш для в случае использования BlockRead задействует опережающее чтение.


> Как получить блок памяти который начинается
> с адреса памяти кратного этому размеру?


"No other memory allocation, including use of the VirtualAlloc function to reserve memory, can take place in the region used for mapping"

Просто задать адрес. Руками.


> В любом случае блок памяти выделенный с помощью функций
> WinApi или Delphi начинается с адреса кратного 65536 + 4
> байта!


Запусти простой пример:

unit main;

interface
uses
 Forms;

type
 TfMain = class(TForm)
   procedure FormCreate(Sender: TObject);
   procedure FormShow(Sender: TObject);
 private
   FMemory: Pointer;
 end;

var
 fMain: TfMain;

implementation
uses
 Windows, SysUtils, Dialogs;

{$R *.dfm}

procedure TfMain.FormCreate(Sender: TObject);
begin
 FMemory := VirtualAlloc(nil, $20000, MEM_RESERVE, PAGE_READWRITE);
 if not Assigned(FMemory) then
   RaiseLastOSError;
end;

procedure TfMain.FormShow(Sender: TObject);
begin
 ShowMessageFmt("The memory reserved at %.8x", [Integer(FMemory)]);
end;

end.


Посмотри, какой адрес он выдаст.
Сравни с тем, как ты получаешь и смотришь адрес.


 
MBo ©   (2004-03-25 06:49) [3]

1. Насколько я понял, ты неправильно понял ;)
Функции MapViewOfFile должно передаваться смещение в файле, кратное 65536, она возвращает указатель на область памяти, выделенную СИСТЕМОЙ, а самому выделять память не надо.
(и адрес этот выровнен на 64K, но нас это обычно не волнует)

MapViewOfFileEx предназначена для специфических применений, для случаев, когда маппирование по каким-то причинам желательно иметь по заданному тобой адресу. (твой пункт 2.)

про 65536+4 - некоторые функции выделения памяти хранят перед выделенным блоком его размер.


 
dmk ©   (2004-03-25 19:16) [4]

Долго я ковырялся с MapViewOfFileEx и пришел к выводу, что
использование Борландовских функций более практичнее.
Огромное Спасибо за ответы. =)



Страницы: 1 вся ветка

Скачать: CL | DM;



Память: 0.47 MB
Время: 0.024 c
14-1083058506
infom
2004-04-27 13:35
2004.05.16
Извините проблема с HTML


14-1082836228
RealRascal
2004-04-24 23:50
2004.05.16
Часов пять сидел за компом без перерыва...


14-1082892916
Dimedrol
2004-04-25 15:35
2004.05.16
Хочу украсить прогу... :-)


3-1082112658
Dimbas
2004-04-16 14:50
2004.05.16
Проблема открытия базы с CD


1-1083490758
AndrewVolkov
2004-05-02 13:39
2004.05.16
Забить exception




   Наверх