Лабораторная работа № 6 Межпроцессное взаимодействие на примере отображаемых в память файлов Цель работы: Изучение механизмов межпроцессного взаимодействия InterProcessCommunication (IPC) в ОС Windows. 1. Теоретические сведения 1.1. Понятие отображаемых файлов (FileMapping) Отображение файла в память — это такой способ работы с файлами, при котором всему файлу или некоторой непрерывной части этого файла ставится в соответствие определённый участок памяти (диапазон адресов оперативной памяти). Это позволяет приложению, включая множество процессов, изменять файл путем чтения и записи прямо в память. Когда два или более процесса получают доступ к одинаковым отображениям файлов, то каждый процесс получает указатель на память в собственном адресном пространстве, которое он может использовать для модифицирования содержимого файла. Отсюда следует, что процессы также должны использовать объект синхронизации, например семафор, чтобы предотвратить разрушение данных в многозадачной среде. Программист может использовать специальный вид отображения файла для обеспечения именованной разделенной памяти между процессами. Если при создании объекта-отображения файла указывается файл подкачки системы (swapping file), то отображение файла создается как блок совместно используемой памяти. Другие процессы также могут получить доступ к этому блоку, открыв такое же отображение файла. Механизм отображения файлов может быть использован процессами, работающими только на локальном компьютере; он не используется для передачи данных по сети. Существует два типа отображаемых в памяти файлов. Постоянные отображаемые в памяти файлы Постоянные отображаемые в памяти файлы связаны с исходным файлом на диске. Данные сохраняются в этот исходный файл, когда последний процесс закончит работу с файлом. Это отображение в памяти подходит для работы с очень большими исходными файлами. Непостоянные отображаемые в памяти файлы Непостоянные отображаемые в памяти файлы не связаны с исходным файлом на диске. Когда последний процесс закончит работу с файлом, данные утрачиваются и файл удаляется функцией сборки мусора. Такие файлы подходят для создания общей памяти для межпроцессного взаимодействия (IPC). 1.2. Организация взаимодействия нескольких процессов через общую область данных Отображаемые в памяти файлы могут совместно использоваться несколькими процессами. Процессы могут сопоставляться с одним отображаемым в памяти файлом при помощи общего имени, которое назначается процессом, создающим файл. Для работы с отображаемым в памяти файлом необходимо создать представление всего файла или его части. Можно также создать несколько представлений одной и той же части отображаемого в памяти файла, создавая таким образом параллельную память. Чтобы два представления оставались параллельными, они должны быть созданы из одного отображаемого в памяти файла. Также может потребоваться использование нескольких представлений, если файл превышает размер пространства логической памяти приложения, доступный для отображения памяти (2 ГБ на компьютере с 32-разрядной архитектурой). Существует два типа представлений: представление потокового доступа и представление произвольного доступа. Необходимо использовать представления потокового доступа для последовательного доступа к файлу; это является предпочтительным для непостоянных файлов и IPC. Представления произвольного доступа являются предпочтительными для работы с постоянными файлами. На следующем рисунке показаны несколько представлений и перекрывающие представления одного и того же одновременно отображаемого в памяти файла. 1.3. Работа с постоянными отображаемыми в памяти файлы Начиная с версии .NET Framework 4, разработчики могут использовать управляемый код для получения отображаемых в памяти файлов. Метод CreateFromFile создает отображаемый в памяти файл из существующего файла на диске. Синтаксис одного из вариантов метода CreateFromFile: public static MemoryMappedFile CreateFromFile( string path, FileMode mode ) Параметры: path - путь к файлу для сопоставления. Тип: System.String mode - режим доступа. Тип: System.IO.FileMode Метод MemoryMappedFile.CreateViewAccessor создает объект для произвольного доступа представления к отображаемому в памяти файлу. В следующем примере создается отображаемое в памяти представление части очень большого файла. using System; using System.IO; using System.IO.MemoryMappedFiles; using System.Runtime.InteropServices; class Program { staticvoid Main(string[] args) { long offset = 0x10000000; // 256 megabytes long length = 0x20000000; // 512 megabytes // Create the memory-mapped file. using (var mmf = MemoryMappedFile.CreateFromFile(@"c:\ExtremelyLargeImage.data", FileMode.Open,"ImgA")) { // Create a random access view, from the 256th megabyte (the offset) // to the 768th megabyte (the offset plus length). using (var accessor = mmf.CreateViewAccessor(offset, length)) { int colorSize = Marshal.SizeOf(typeof(MyColor)); MyColor color; // Make changes to the view. for (long i = 0; i < length; i += colorSize) { accessor.Read(i, out color); color.Brighten(10); accessor.Write(i, ref color); } } } } } publicstruct MyColor { publicshort Red; publicshort Green; publicshort Blue; publicshort Alpha; // Make the view brigher. publicvoid Brighten(short value) { Red = (short)Math.Min(short.MaxValue, (int)Red + value); Green = (short)Math.Min(short.MaxValue, (int)Green + value); Blue = (short)Math.Min(short.MaxValue, (int)Blue + value); Alpha = (short)Math.Min(short.MaxValue, (int)Alpha + value); } } 1.4. Работа с непостоянными отображаемыми в памяти файлы Методы CreateNew и CreateOrOpen создают отображаемый в памяти файл, которому не соответствует файл на диске. Полный синтаксис метода public static MemoryMappedFile CreateNew( string mapName, long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability inheritability ) Параметры mapName Тип: System.String Имя, присваиваемое отображаемому в памяти файлу. capacity Тип: System.Int64 Максимальный размер, выделяемый отображаемому в памяти файлу, в байтах. access Тип: System.IO.MemoryMappedFiles.MemoryMappedFileAccess Одно из значений перечисления, определяющее разрешенный тип доступа к отображаемому в памяти файлу. Значение по умолчанию: ReadWrite. options Тип: System.IO.MemoryMappedFiles.MemoryMappedFileOptions Побитовое сочетание значений перечисления, которое задает параметры выделения памяти для отображаемого в памяти файла. memoryMappedFileSecurity Тип: System.IO.MemoryMappedFiles.MemoryMappedFileSecurity Разрешения, которые могут быть предоставлены для доступа к файлам и операций с отображаемыми в памяти файлами. Этот параметр может иметь значение null. inheritability Тип: System.IO.HandleInheritability Одно из значений перечисления, определяющее, может ли дескриптор отображаемого в памяти файла наследоваться дочерним процессом. Значение по умолчанию: None. Возвращаемое значение Тип: System.IO.MemoryMappedFiles.MemoryMappedFile Отображаемый в памяти файл с заданными характеристиками. Один из вариантов синтаксиса метода CreateNew: public static MemoryMappedFile CreateNew( string mapName, long capacity ) Параметры: mapName - имя, присваиваемое отображаемому в памяти файлу. Тип: System.String capacity - максимальный размер, выделяемый отображаемому в памяти файлу, в байтах. Тип: System.Int64 Метод OpenExisting открывает существующий размещенный в памяти файл с заданным именем в системной памяти. public static MemoryMappedFile OpenExisting( string mapName ) Следующий пример показывает работу трех отдельных процессов (консольных приложений), которые записывают логические значения в непостоянный отображаемый в памяти файл. Для синхронизации работы с отображаемым в памяти файлом используется объект мьютекс. ПроцессА using using using using System; System.IO; System.IO.MemoryMappedFiles; System.Threading; class Program { // Process A: staticvoid Main(string[] args) { using (MemoryMappedFile mmf = MemoryMappedFile.CreateNew("testmap", 10000)) { bool mutexCreated; Mutex mutex = new Mutex(true, "testmapmutex", out mutexCreated); using (MemoryMappedViewStream stream = mmf.CreateViewStream()) { BinaryWriter writer = new BinaryWriter(stream); writer.Write(1); } mutex.ReleaseMutex(); Console.WriteLine("Start Process B and press ENTER to continue."); Console.ReadLine(); Console.WriteLine("Start Process C and press ENTER to continue."); Console.ReadLine(); mutex.WaitOne(); using (MemoryMappedViewStream stream = mmf.CreateViewStream()) { BinaryReader reader = new BinaryReader(stream); Console.WriteLine("Process A says: {0}", reader.ReadBoolean()); Console.WriteLine("Process B says: {0}", reader.ReadBoolean()); Console.WriteLine("Process C says: {0}", reader.ReadBoolean()); } mutex.ReleaseMutex(); } } } ПроцессB using using using using System; System.IO; System.IO.MemoryMappedFiles; System.Threading; class Program { // Process B: staticvoid Main(string[] args) { try { using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("testmap")) { Mutex mutex = Mutex.OpenExisting("testmapmutex"); mutex.WaitOne(); using (MemoryMappedViewStream stream = mmf.CreateViewStream(1, 0)) { BinaryWriter writer = new BinaryWriter(stream); writer.Write(0); } mutex.ReleaseMutex(); } } catch (FileNotFoundException) { Console.WriteLine("Memory-mapped file does not exist. Run Process A first."); } } } ПроцессC using using using using System; System.IO; System.IO.MemoryMappedFiles; System.Threading; class Program { // Process C: staticvoid Main(string[] args) { try { using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("testmap")) { Mutex mutex = Mutex.OpenExisting("testmapmutex"); mutex.WaitOne(); using (MemoryMappedViewStream stream = mmf.CreateViewStream(2, 0)) { BinaryWriter writer = new BinaryWriter(stream); writer.Write(1); } mutex.ReleaseMutex(); } } catch (FileNotFoundException) { Console.WriteLine("Memory-mapped file does not exist. Run Process A first, then B."); } } } Метод MemoryMappedFile.CreateViewStream создает поток для последовательного доступа представления к отображаемому в памяти файлу. Данный метод перегружен. Может использоваться без параметров и принимать несколько параметров. Синтаксис одной из перегрузок MemoryMappedFile.CreateViewStream: public MemoryMappedViewStream CreateViewStream( long offset, long size ) Параметры offset - байт, с которого должно начинаться представление. Тип:System.Int64 size - размер представления. Укажите 0 (нуль), чтобы создать представление, которое начинается с offset и заканчивается приблизительно в конце отображаемого в памяти файла. Тип: System.Int64 2. Практическое задание Разработать программу согласно варианту: Вариант Задачи 1 Реализовать нахождение максимального элемента матрицы с помощью нескольких процессов: каждый процесс получает от ведущего процесса строку матрицы, находит максимальный элемент в строке. Ведущий процесс находит наибольшее из переданных ему значений. Взаимодействие выполнить с помощью отображаемых файлов. 2 Реализовать нахождение с помощью нескольких процессов: каждый процесс выполняет перемножение строки первой матрицы на столбец второй (в соответствии с правилом умножения матриц). При необходимости процессам, выполняющим умножение, может быть отправлено несколько заданий. Взаимодействие выполнить с помощью отображаемых файлов. 3 Реализовать алгоритм блочной сортировки по возрастанию файла целых чисел с помощью нескольких процессов. Каждый процесс, выполняющий сортировку, получает свою часть файла от ведущего процесса и сортирует его. Ведущий процесс выполняет упорядочивание уже отсортированных блоков. При необходимости ведомым процессам может быть выделено более одного задания на сортировку. Взаимодействие выполнить с помощью отображаемых файлов. 4 Реализовать обмен текстовыми сообщениями между несколькими процессами. Обеспечить подтверждение приема сообщения адресатом или, в случае потери сообщения, повторную его передачу. Взаимодействие выполнить с помощью отображаемых файлов. 5 Реализовать нахождение в матрице столбца, содержащего наименьшее количества нулевых элементов с помощью нескольких процессов: каждый процесс получает от ведущего процесса столбец матрицы, находит количество нулевых элементов в столбце. Взаимодействие выполнить с помощью отображаемых файлов. 6 Реализовать нахождение среднего значения элементов матрицы с помощью нескольких процессов: каждый процесс получает от ведущего процесса столбец матрицы, находит среднее значения элементов в столбце. Ведущий процесс находит среднее из переданных ему значений. Взаимодействие выполнить с помощью отображаемых файлов. 7 Реализовать нахождение минимального элемента матрицы с помощью нескольких процессов: каждый процесс получает от ведущего процесса строку матрицы, находит минимальный элемент в строке. Ведущий процесс находит наименьшее из переданных ему значений. Взаимодействие выполнить с помощью отображаемых файлов. 8 Реализовать нахождение строки матрицы, содержащей максимальное количество ненулевых значений с помощью нескольких процессов: каждый процесс получает от ведущего процесса строку матрицы, находит количество ненулевых элементов в строке. Ведущий процесс находит наибольшее из переданных ему значений. Взаимодействие выполнить с помощью отображаемых файлов. 9 Реализовать нахождение строки матрицы, содержащей минимальное количество положительных элементов с помощью нескольких процессов: каждый процесс получает от ведущего процесса строку матрицы, находит количество положительных элементов в строке. Ведущий процесс находит наименьшее из переданных ему значений. Взаимодействие выполнить с помощью отображаемых файлов. 10 Реализовать нахождение в матрице строки, содержащей наибольшее количество ненулевых элементов с помощью нескольких процессов: каждый процесс получает от ведущего процесса столбец матрицы, находит количество ненулевых элементов. Взаимодействие выполнить с помощью отображаемых файлов. 11 Реализовать алгоритм блочной сортировки по убыванию файла целых чисел с помощью нескольких процессов. Каждый процесс, выполняющий сортировку, получает свою часть файла от ведущего процесса и сортирует его. Ведущий процесс выполняет упорядочивание уже отсортированных блоков. При необходимости ведомым процессам может быть выделено более одного задания на сортировку. Взаимодействие выполнить с помощью отображаемых файлов 12 Реализовать нахождение среднего значения элементов матрицы с помощью нескольких процессов: каждый процесс получает от ведущего процесса строку матрицы, находит среднее значения элементов в строке. Ведущий процесс находит среднее из переданных ему значений. Взаимодействие выполнить с помощью отображаемых файлов. 13 Реализовать нахождение строки матрицы, содержащей максимальное количество ненулевых значений с помощью нескольких процессов: каждый процесс получает от ведущего процесса строку матрицы, находит количество ненулевых элементов в строке. Ведущий процесс находит наибольшее из переданных ему значений. Взаимодействие выполнить с помощью отображаемых файлов. 14 Реализовать нахождение суммы элементов матрицы с помощью нескольких процессов: каждый процесс получает от ведущего процесса строку матрицы, находит сумму элементов в строке. Ведущий процесс находит сумму переданных ему значений. Взаимодействие выполнить с помощью отображаемых файлов. 15 Реализовать нахождение модуля суммы элементов матрицы с помощью нескольких процессов: каждый процесс получает от ведущего процесса столбец матрицы, находит модуль суммы элементов в столбце. Ведущий процесс находит модуль суммы переданных ему значений. Взаимодействие выполнить с помощью отображаемых файлов. 3. Контрольные вопросы 1. Что такое отображение файла в память? 2. Для каких целей служит отображение файлов? 3. Перечислите типы отображаемых файлов и объясните их отличие. 4. Возможно ли задание прав доступа к отображаемым файлам? Использованные источники 1. http://msdn.microsoft.com/ruru/library/system.io.memorymappedfiles.memorymappedfile(v=vs.110).aspx 2. http://msdn.microsoft.com/ru-ru/library/dd997372.aspx