Прогон программы, демонстрирующей передачу информации от одного процесса к другому через разделяемую память

Рассмотрим текст двух программ first.c и second.c

First.c

#include <windows.h>

#include <stdio.h>

void main(void){

HANDLE hMapFile;

LPVOID lpMapAddress;

HANDLE hFile;

char * String;

hFile = CreateFile("MyFile.txt", // имя файла

GENERIC_READ | GENERIC_WRITE, // файл для чтения и записи

FILE_SHARE_READ| FILE_SHARE_WRITE,// режим совместного доступа

NULL, // защита по умолчанию

OPEN_EXISTING, // файл должен существовать

FILE_ATTRIBUTE_NORMAL, // атрибуты файла

NULL); // файл атрибутов

if (hFile == INVALID_HANDLE_VALUE) printf("Could not open file\n");

hMapFile = CreateFileMapping(hFile, // описатель отображаемого файла

NULL, // атрибуты защиты по умолчанию

PAGE_READWRITE, // режим доступа

0, // старшее двойное слово размера буфера

0, // младшее двойное слово размера буфера

"MyFileObject"); // имя объекта

if (hMapFile == NULL) printf("Could not create file-mapping object.\n");

lpMapAddress = MapViewOfFile(hMapFile, // описатель отображаемого файла

FILE_MAP_ALL_ACCESS, // режимы доступа

0, 0, // отображение файла с начала

0); // отображение целого файла

if (lpMapAddress == NULL) printf("Could not map view of file.\n");

String = (char *)lpMapAddress;

sprintf(String, "Hello, world");

getchar();

}

Пример 10.1. (html, txt)

Second.c

#include <windows.h>

#include <stdio.h>

void main(void){

HANDLE hMapFile;

LPVOID lpMapAddress;

HANDLE hFile;

char * String;

hFile = CreateFile("MyFile.txt", // имя файла

GENERIC_READ | GENERIC_WRITE, // файл для чтения и записи

FILE_SHARE_READ| FILE_SHARE_WRITE,// режим совместного доступа

NULL, // защита по умолчанию

OPEN_EXISTING, // файл должен существовать

FILE_ATTRIBUTE_NORMAL, // атрибуты файла

NULL); // файл атрибутов

if (hFile == INVALID_HANDLE_VALUE)

{

printf("Could not open file\n"); // process error

}

hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, // разрешение чтения-записи

FALSE, // описатель не наследуется

"MyFileObject"); // имя объекта проецируемого файла

if (hMapFile == NULL) printf("Could not open Filemapping\n");

lpMapAddress = MapViewOfFile(hMapFile, // описатель отображаемого файла

FILE_MAP_ALL_ACCESS, // режимы доступа

0, 0, // отображение файла с начала

0); // отображение целого файла

if (lpMapAddress == NULL) printf("Could not map view of file.\n");

String = (char *)lpMapAddress;

printf("%s\n", String);

getchar();

}

Пример 10.2. (html, txt)

Программа first создает в своем адресном пространстве буфер разделяемой памяти, а программа second отображает тот же самый буфер в свое адресное пространство. Затем программа first записывает в этот буфер текстовую строку, а программа second выводит ее содержимое на экран. Обе программы должны быть запущены из одного каталога с уже существующим файлом MyFile.txt. Для наглядности рекомендуется, чтобы длина файла была изначально больше длины строки "Hello, world".

Написание, компиляция и выполнение программы обмена информацией через разделяемый буфер памяти с использованием системной области выгрузки

Рекомендуется модифицировать предыдущую программу для передачи информации через фрагмент разделяемой памяти, спроецированной не в обычный файл, а в системную область выгрузки. Для этого в качестве параметра описателя файла функции CreateFileMapping нужно указать INVALID_HANDLE_VALUE.

Физическая память

Физическая (в данном случае оперативная) память и внешняя память также описываются соответствующими структурами данных.

ОС Windows поддерживает до 4 Гб (некоторые версии и более) физической памяти. Память более 32 Мб считается "большой". Объем памяти можно посмотреть на вкладке "Быстродействие" диспетчера задач. Информация о состоянии страниц физической памяти и их принадлежности процессам находится в базе данных PFN (page frame number), а использование внешней памяти осуществляется через страничные файлы или файлы выгрузки.

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

Структура системных страничных файлов недокументирована. Известно, что в системе может быть до 16 страничных файлов. Информация о страничных файлах находится в разделе HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PagingFiles реестра, однако управление страничными файлами рекомендуется осуществлять через апплет "система" административной консоли управления. У каждого файла подкачки есть начальный и максимальный размер. С целью уменьшения вероятной фрагментации их создают максимального размера.

Полезную информацию об использовании страничных файлов можно получить, наблюдая за счетчиками на вкладке "Производительность", а также с помощью диспетчера задач. Например, счетчик "Page File Bytes" показывает общее число переданных страниц.

Рабочие наборы процессов

В результате связывания адресов часть виртуальных страниц процесса непосредственно отображается в страницы физической памяти. Это множество страниц иногда называют резидентным множеством процесса. В теории операционных систем известно также понятие "рабочего множества" процесса - совокупности страниц, активно использующихся вместе, которая позволяет процессу в течение некоторого периода времени производительно работать, избегая большого количества page fault`ов.

Согласно документации по ОС Windows, рабочим набором процесса называется совокупность физических страниц, выделенных процессу. Размер рабочего набора должен находиться в некоторых пределах, определяемых константами системы в зависимости от суммарного объема физической памяти. Например, если физической памяти достаточно, то рабочий набор процесса должен быть в диапазоне от 50 до 345 страниц. Имея привилегию Increase Scheduling Priority (о привилегиях см. часть V), эти значения можно менять при помощи функции SetProcessWorkingSet.

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

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

Наши рекомендации