Windows для профессионалов

       

Особенности проецирования файлов на разных платформах


Механизм проецирования файлов в Windows 2000 и Windows 98 реализован по-раз ному Вы должны знать об этих отличиях, поскольку они могут повлиять на код про грамм и целостность используемых ими данных

В Windows 98 представление всегда проецируется на раздел адресного простран ства, расположенный в диапазоне от 0x80000000 до 0xBFFFFFFF. Значит, после успеш ного вызова функция MapViewOfFile вернет какой-нибудь адрес из этого диапазона. Но вспомните: данные в этом разделе доступны всем процессам. Если один из про цессов отображает сюда представление объекта "проекция файла, то принадлежащие этому объекту данные физически доступны всем процессам, и уже неважно: проеци руют ли они сами представление того же объекта. Если другой процесс вызывает MapViewOJFile, используя тот же объект "проекция файла", Windows 98 возвращает адрес памяти, идентичный тому, что она сообщила первому процессу. Поэтому два процесса обращаются к одним и тсм же данным и представления их объектов коге рентны.

В Windows 98 один процесс может вызвать MapViewOJFile и, воспользовавшись какой-либо формой межпроцессной связи, передать возвращенный ею адрес памяти потоку другого процесса. Как только этот поток получит нужный адрес, ему уже нич то не помешает получить доступ к тому же представлению объекта "проекция фай ла". Но прибегать к такой возможности не следует по двум причинам:

  • приложение не будет работать в Windows 2000 (и я только что рассказал — почему);

  • если первый процесс вызовет UnmapViewOfFile, регион адресного простран ства освободится. А значит, при попытке потока второго процесса обратиться к участку памяти, где когда-то находилось представление, возникнет наруше ние доступа.
  • Чтобы второй процесс получил доступ к представлению проецируемого файла, его поток тоже должен вызвать MapViewOfFile Тогда система увеличит счетчик числа пользователей объекта "проекция файла". И если первый процесс обратится к Unmap ViewOfFile, регион адресного пространства, занятый представлением, не будет осво божден, пока второй процесс тоже не вызовет UnmapViewOfFile. А вызвав MapView OfFile, второй процесс получит тот же адрес, что и первый.
    Таким образом, необхо димость в передаче адреса от первого процесса второму отпадает.

    В Windows 2000 механизм проецирования файлов реализован удачнее, чем в Win dows 98, потому что Windows 2000 для доступа к файловым данным в адресном про странстве требует вызова MapViewOfFile. При обращении к этой функции система резервирует для проецируемого файла закрытый регион адресного пространства, и никакой другой процесс нс получает к нему доступ автоматически. Чтобы посторон ний процесс мог обратиться к данным того же объекта "проекция файла", сго поток тоже должен вызвать MapViewOfFile, и система отведет регион для представления объекта в адресном пространстве второго процесса.

    Адрес, полученный при вызове MapViewOfFile первым процессом, скорее всего не совпадет с тем, что получит при ее вызове второй процесс, - даже несмотря на то что оба процесса проецируют представление одного и того же объекта. И хотя в Windows 98 адреса, получаемые процессами при вызове MapViewOfFile, совпадают,

    лучше не полагаться на эту особенность — иначе приложение не станет работать в Windows 2000!

    Рассмотрим еще одно различие механизмов проецирования файлов у Windows 2000 и Windows 98. Взгляните на текст программы, проецирующей два представления един ственного объекта "проекция файла".

    #include <Windows.h>



    int WINAPI WinMain(HINSTANCE hinstExe, HINSTANCE, PTSTR pszCmdLine, int nCmdShow)
    {

    // открываем существующий файл; он должен быть больше 64 Кб
    HANDLE hFile = CreateFile(pszCmdLine, GENERIC_READ | GENERlC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    // создаем объект "проекция файла", связанный с файлом данных
    HANDLE hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);

    // проецируем представление всего файла на наше адресное пространство
    PBYTE pbFilc = (PBYTE)MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, 0);

    // проецируем второе представление файла, начиная со смещения 64 Кб

    PBYTE pbFile2 = (PBYTE)MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 65536, 0);



    if ((pbFile + 65536) == pbFilft2))
    {

    // если адреса перекрываются, оба предсгавления проецируются на один
    // регион, и мы работаем в Windows 98
    MessageBox(NULL, "We are running under Windows 98", NULL, MB_OK);

    }
    else
    {

    // если адреса не перекрываются, каждое представление размещается в
    // своем регионе адресного пространства, и мы работаем в Windows 2000
    MessageBox(NULL, "We are running under Windows 2000", NULL, MB_OK),

    }

    UnmapViewOfFile(pbFile2);
    UnmapViewOfFile(pbFile);
    CloseHandle(hFileMapping);
    CloseHandle(hFile};

    return(0);

    }

    Когда приложение в Windows 98 отображает на адресное пространство представ ление объекта "проекция файла", ему отводится регион, достаточно большой для раз мещения всего объекта Это происходит, даже если Вы просите MapViewOfFile спрое цировать лишь малую часть такого объекта. Поэтому спроецировать объект размером 1 Гб не удастся, даже если указать, что представление должно быть не более 64 Кб.

    При вызове каким-либо процессом функции MapViewOfFile ему возвращается ад рес в пределах региона, зарезервированного для целого объекта "проекция файла". Так что в покязанной выше программе первый вызов этой функции дает базовый адрес региона, содержащего весь спроецированный файл, а второй — адрес, смещенный "вглубь" того же региона на 64 Кб.

    Wmdows 2000 и здесь ведет себя совершенно иначе Два вызова функции МарView OfFile (как в показанном выше коде) приведут к тому, что будут зарезервированы два

    региона адресного пространства. Объем первого будет равен размеру объекта "про екция файла", объем второго — размеру объекта минус 64 Кб. Хотя регионы - раз ные, система гарантирует когерентность данных, так как оба представления созданы на основе одного объекта "проекция файла" А в Windows 98 такие представления когерентны потому, что они расположены в одном участке памяти


    Содержание раздела