Отображение файлов в память

Отображение файла является процессом отображения секторов диска файла в пространство виртуальной памяти процесса. После того, как отображенный, Ваши доступы к приложениям файл, как будто это был полностью резидентный объект в памяти. Поскольку Вы считываете данные из отображенного указателя файла, страниц ядра в надлежащих данных, и возвращает его Вашему приложению.

Несмотря на то, что отображение файлов может предложить огромные преимущества производительности, это не является надлежащим во всех случаях. Следующие разделы объясняют, когда отображение файла может помочь Вам и как Вы идете о выполнении его в Вашем коде.

Выбор, когда отобразить файлы

При решении, отобразить ли файлы, имейте в виду, что полная цель состоит в том, чтобы сократить передачи между диском и памятью. Отображение файла может помочь Вам в некоторых случаях, но не всем. Чем больше файла, который Вы отображаете в память, тем менее полезное отображение файла становится.

Перед отображением любых файлов в память удостоверьтесь, что Вы понимаете свои типичные образцы использования файла. Инструменты могут помочь Вам идентифицировать, где Ваши файлы доступов к приложениям и сколько времени те операции берут. Для любых операций, занимающих больше времени, чем ожидаемый, можно тогда смотреть код, чтобы определить, могло ли бы быть полезным отображение файла.

Отображение файла является эффективным при следующих ситуациях:

Вы не должны использовать файл, отображающийся в следующих ситуациях:

Для больших последовательных операций чтения Вы - более обеспеченное кэширование диска отключения и чтение файла в небольшой буфер памяти.

Протесты отображения файла

Даже в ситуациях, где Вы думаете, отображение файла идеально, существуют все еще некоторые протесты, которые могут применяться. В частности Вы не можете хотеть отображать файлы в следующих ситуациях:

Случайным образом получая доступ к очень большому файлу, это часто - лучшая идея отобразить только небольшую часть файла за один раз. Проблема с отображением больших файлов состоит в том, что файл использует активную память. Если файл является достаточно большим, система могла бы быть вынуждена разбить на страницы другие части памяти для загрузки файла. Отображение больше чем одного файла в память просто соединяет эту проблему.

Для файлов на съемных или сетевых дисках необходимо избежать отображать файлы в целом. Если Вы отображаете файлы на съемном или сетевом диске, и тот диск размонтирован или исчезает по другой причине, получение доступ к расширенной памяти может вызвать ошибку шины и разрушить Вашу программу. Если Вы настаиваете на том, чтобы отображать эти типы файлов, несомненно, установят сигнальный обработчик в Вашем приложении, чтобы захватить и обработать условие ошибки шины. Даже с сигнальным установленным обработчиком, текущий поток Вашего приложения может блокировать, пока это не получает тайм-аут от попытки получить доступ к сетевому файлу. Этот период тайм-аута может подать Вашу заявку, кажутся подвешенными и безразличными, и легко избегается, не отобразив файлы во-первых.

Отображение файла на корневом устройстве всегда безопасно. (Если корневое устройство так или иначе демонтировано или недоступно, система не может продолжать работать.) Обратите внимание на то, что корневой каталог пользователя не требуется, чтобы быть на корневом устройстве.

Пример отображения файла

Перечисление 1-1 демонстрирует отображение памяти с помощью уровня BSD mmap и munmap функции. Отображенный файл занимает определенную системой часть виртуального адресного пространства приложения до munmap используется для неотображения файла. Для получения дополнительной информации об этих функциях, посмотрите mmap и munmap.

Перечисление 1-1  , Отображающее файл в виртуальную память

void ProcessFile( char * inPathName )
{
    size_t dataLength;
    void * dataPtr;
 
    if( MapFile( inPathName, &dataPtr, &dataLength ) == 0 )
    {
        //
        // process the data and unmap the file
        //
 
        // . . .
 
        munmap( dataPtr, dataLength );
    }
}
 
 
// MapFile
// Return the contents of the specified file as a read-only pointer.
//
// Enter:inPathName is a UNIX-style “/”-delimited pathname
//
// Exit:    outDataPtra     pointer to the mapped memory region
//          outDataLength   size of the mapped memory region
//          return value    an errno value on error (see sys/errno.h)
//                          or zero for success
//
int MapFile( char * inPathName, void ** outDataPtr, size_t * outDataLength )
{
    int outError;
    int fileDescriptor;
    struct stat statInfo;
 
    // Return safe values on error.
    outError = 0;
    *outDataPtr = NULL;
    *outDataLength = 0;
 
    // Open the file.
    fileDescriptor = open( inPathName, O_RDONLY, 0 );
    if( fileDescriptor < 0 )
    {
       outError = errno;
    }
    else
    {
        // We now know the file exists. Retrieve the file size.
        if( fstat( fileDescriptor, &statInfo ) != 0 )
        {
            outError = errno;
        }
        else
        {
            // Map the file into a read-only memory region.
            *outDataPtr = mmap(NULL,
                                statInfo.st_size,
                                PROT_READ,
                                0,
                                fileDescriptor,
                                0);
            if( *outDataPtr == MAP_FAILED )
            {
                outError = errno;
            }
            else
            {
                // On success, return the size of the mapped file.
                *outDataLength = statInfo.st_size;
            }
        }
 
        // Now close the file. The kernel doesn’t use our file descriptor.
        close( fileDescriptor );
    }
 
    return outError;
}