Вивчення засобів обміну даними між процесами ми почнемо з файлів, які відображаються на згадку. Цей спосіб має високу швидкодію, оскільки дані передаються між процесами безпосередньо через віртуальну пам'ять.
Методика роботи з файлами, які відображаються на згадку, була описана в першому розділі. Ця методика може бути використана без змін для організації передачі даних між процесами, проте ми все ж таки зробимо деякі зауваження.
Нагадаємо, що відображення створюється функцією CreateFileMapping.
Ось фрагмент коду із програми Oem2Char, в якому створюється відображення файлу, а потім виконується відображення цього файлу на згадку:
Тут як перший параметр для функції CreateFileMapping ми передаємо ідентифікатор файлу, відкритого функцією CreateFile. Останній параметр вказаний як NULL, тому відображення немає імені.
Якщо відображення буде використовуватися для передачі даних між процесами, зручно вказати ім'я. Користуючись цим ім'ям, інші процеси зможуть відкрити функцію OpenFileMapping.
Інше зауваження стосується ідентифікатора файлу, який передається функції CreateFileMapping через перший параметр. Якщо ви створюєте відображення тільки для забезпечення передачі даних між процесами, вам не потрібно створювати файл на диску комп'ютера. Вказавши значення ідентифікатора файлу (HANDLE)0xFFFFFFFF, ви створите відображення безпосередньо у віртуальній пам'яті без використання додаткового файлу.
Нижче наведено фрагмент коду, в якому створюється відображення з ім'ям $MyVerySpecialFileShareName$, причому це відображення створюється у віртуальній пам'яті:
Після того, як ви створили об'єкт-відображення, слід виконати відображення файлу в пам'ять приЗа допомогою функції MapViewOfFile, як це було показано вище. У разі успіху ця функція поверне покажчик на відображену область пам'яті.
Отже, перший процес створив відображення. Другий процес, який виконуватиме обмін даними з першим процесом, повинен відкрити це відображення на ім'я за допомогою функції OpenFileMapping, наприклад, так:
Далі друга програма виконує відображення, викликаючи функцію MapViewOfFile:
Користуючись значенням, отриманим від функції MapViewOfFile, друга програма отримує покажчик на відображену область пам'яті. Фізично ця область перебуває у тих сторінках віртуальної пам'яті, як і область, створена першим процесом. Таким чином, два процеси отримали вказівники на спільні сторінки пам'яті.
Перед завершенням своєї роботи процеси повинні скасувати відображення файлу та звільнити ідентифікатор створеного об'єкта-відображення:
Додаток Fmap/Server
Для ілюстрації методики обміну даними між різними процесами з використанням файлів, що відображаються на згадку, ми підготували вихідні тексти двох консольних додатків: Fmap/Server і Fmap/Client. Ці програми працюють у парі (рис. 2.1).
Мал. 2.1. Взаємодія консольних програм Fmap/Server і Fmap/Client
Програма Fmap/Server створює відображення та два об'єкти-події. Перший об'єкт призначений до роботи з клавіатурою, другий - виявлення моменту завершення програми Fmap/Client. Об'єкти-події описані нами в попередньому томі “Бібліотеки системного програміста”, присвяченому програмуванню для операційної системи Microsoft Windows NT.
Додаток Fmap/Client відкриває створене відображення та об'єкти-події, а потім у циклі вводить символи з клавіатури, перемикаючи один із об'єктів-подій у зазначенестан під час введення кожного символу. Коди введених символів записуються у відображену пам'ять.
У міру того, як користувач вводить символи у вікні програми Fmap/Client, програма Fmap/Server відображає їх у своєму вікні, отримуючи коди введених символів з відображеної пам'яті. Для синхронізації використовується подія, виділена для роботи з клавіатурою.
Якщо користувач натискає клавішу у вікні програми Fmap/Client, ця програма відзначає обидві події та завершує свою роботу. Програма Fmap/Server, виявивши, що другий об'єкт-подія опинився у зазначеному стані, також завершує свою роботу. Таким чином, якщо завершити роботу програми Fmap/Client, то програма Fmap/Server також буде завершено.
Вихідний текст програми Fmap/Server представлений у лістингу 2.1.
Лістинг 2.1. Файл fmap/server/server.c
У глобальних змінних hEventChar та hEventTermination зберігаються ідентифікатори об'єктів-подій, призначених, відповідно, для роботи з клавіатурою та для фіксації моменту завершення роботи програми Fmap/Client. Ці ж ідентифікатори записуються в глобальний масив hEvents, який використовується функцією WaitForMultipleObjects.
Глобальні імена об'єктів-подій зберігаються в змінних lpEventName та lpEventTerminationName.
Ім'я відображення записується в масив lpFileShareName, а ідентифікатор цього відображення - у глобальну змінну hFileMapping.
Функція main програми Fmap/Server створює два об'єкта-події, користуючись при цьому функцією CreateEvent. Опис цієї функції ви знайдете у попередньому томі “Бібліотеки системного програміста”.
Далі функція main створює об'єкт-відображення та виконує відображення, викликаючи для цього, відповідно, функції CreateFileMapping таMapViewOfFile. Оскільки як ідентифікатор файлу функції CreateFileMapping передається значення (HANDLE)0xFFFFFFFF, відображення буде створено безпосередньо у віртуальній пам'яті без використання файлу, розташованого на диску.
Після ініціалізації масиву hEvents функція main запускає цикл, у якому виконується очікування подій та виведення символів, записаних додатком Fmap/Client у відображену область віртуальної пам'яті.
Для очікування двох подій використовується функція WaitForMultipleObjects. Через третій параметр цієї функції передається значення FALSE, тому очікування припиняється у тому випадку, якщо будь-яка подія переходить у зазначений стан.
У тому випадку, коли в зазначений стан перейшов об'єкт-подія hEventTermination, функція WaitForMultipleObjects повертає значення WAIT_OBJECT_0. Виявивши це, функція main завершує свою роботу, тому що подія hEventTermination відзначається при завершенні роботи клієнтської програми Fmap/Client.
Якщо ж у зазначений стан переходить об'єкт-подія hEventChar, функція WaitForMultipleObjects повертає значення WAIT_OBJECT_0 + 1. У цьому випадку функція main читає перший байт з відображеної області пам'яті і виводить його в консольне вікно за допомогою знайомої вам з програмування для MS-DOS функції :
Перед завершенням функція main закриває ідентифікатори об'єктів-подій, скасовує відображення та звільняє ідентифікатор цього відображення.
Додаток Fmap/Client
Вихідні тексти програми Fmap/Client, призначеної для спільної роботи з додатком Fmap/Server, представлені у лістингу 2.2.
Лістинг 2.2. Файл fmap/client/client.c
Після створення об'єктів-подій, призначених для синхронізації роботи здодатком Fmap/Server, функція main програми Fmap/Client відкриває відображення за допомогою функції OpenFileMapping, як показано нижче:
Як ім'я відображення тут вказується рядок $MyVerySpecialFileShareName$ - такий самий, що й у додатку Fmap/Server.
Далі у разі успіху виконується відображення на згадку:
Якщо відображення виконано успішно, в глобальну змінну lpFileMap записується вказівник на відображену область пам'яті, а потім запускається цикл введення символів із клавіатури.
Символи вводяться за допомогою функції консольного введення getche. Результат зберігається в першому байті відображеної області пам'яті, звідки його братиме для виведення програму Fmap/Server:
Після виконання запису функція main встановлює у зазначений стан об'єкт-подію, призначену для роботи з клавіатурою.
Якщо користувач натискає у вікні програми Fmap/Client клавішу 27, цикл переривається. Обидва об'єкти-події перетворюються на зазначений стан, після чого ідентифікатори цих об'єктів звільняються.
Перед завершенням роботи функція main скасовує відображення файлу та звільняє ідентифікатор об'єкта-відображення.