Полезное для программистов:

Фриланс
Новости
Статьи
   
Рубрики:


Создание shared-переменной

Поиск:
Чуть-чуть теории
Разделяемая между процессами переменная (shared-переменная) - это участок памяти, выделяемый в специальном shared-сегменте DLL. Для создания и доступа к такой переменной требуется создать DLL с shared-сегментом, разместить в нём переменную(-е), и обязательно проинициализировать каждую переменную начальным значением.

Далее можно пойти двумя путями. Наиболее простой - дополнительно объявить shared-переменную экспортируемой, что позволит обращаться к ней из EXE как к обычной глобальной переменной. Второй способ - сложнее, но позволит избежать некоторых проблем при выполнении неатомарных операций чтения/записи в shared-переменных. Заключается он в следующем:
1) Создать в DLL специальные экспортируемые функции для доступа к shared-переменным (в дальнейшем каждый процесс будет обращаться к shared-переменной используя именно эти функции)
2) Для доступа к shared-переменной, процесс подключает вышеописанную DLL-ку и записывает/читает значение переменной, используя функции из пункта 1. Для исключения конфликтов между двумя различными процессами (например, один процесс записывает данные в shared-массив, а другой пытается прочитать), можно организовать синхронизацию доступа (с помощью событий, мьютексов или семафоров).

Практический пример №1
Создадим shared-переменную первым способом (экспортируемая shared-переменная):
1) Создаём DLL (TestDll.dll, с макросами TESTDLL_API -- как её сделать, описано в этом разделе FAQ), добавляем в конец .H/.CPP-файлов строки:
Цитата
TestDll.h

extern TESTDLL_API int SharedIntVar;  // наша shared-переменная


TestDll.cpp

#pragma data_seg(".SHAREDSEG")   // создали shared-сегмент

// инициализация shared-переменной
TESTDLL_API int SharedIntVar = 0;

#pragma data_seg ()    // вышли из shared-сегмента
#pragma comment(linker, "/SECTION:.SHAREDSEG,RWS")

2) Подключаем созданную DLL-ку (способ подключения без LoadLibrary описан в том же разделе FAQ), к новому проекту TestExe.exe (пусть это будет проект с главным окном в виде диалога), кидаем на диалог две кнопки (обозначим их как Get и Set), и один Edit (там будет отображаться значение shared-переменной), создаём обработчики нажатия на кнопки Get/Set:
Цитата
void CTestExeDlg::OnButtonGet()
{
     // здесь мы читаем shared-переменную:
     int  iValue = SharedIntVar;  

     // обновляем текст в Edit-е
     CString strValue;
     strValue.Format("%i", iValue);
     GetDlgItem(IDC_EDIT1)->SetWindowText(strValue);
}

void CTestExeDlg::OnButtonSet()
{
     // берём текст из Edit-а:
     CString strValue;
     GetDlgItem(IDC_EDIT1)->GetWindowText(strValue);

     // здесь мы записываем в shared-переменную:
     SharedIntVar = atoi(strValue);
}

Итак, мы получили приложение. Запустим его в двух-трёх копиях понажимаем кнопки Get и Set для чтения/записи shared-переменной --- и визуально убедимся, что одна числовая переменная доступна одновременно нескольким процессам.


Практический пример №2
Создадим shared-массив, состоящий из ста символов char.
1) Создаём ту же DLL-ку, что и в примере №1, добавляем код в .H/.CPP:
Цитата
TestDll.h

// эти функции будут использоваться для доступа к shared-массиву
TESTDLL_API bool GetSharedString(char *buffer_to);
TESTDLL_API bool SetSharedString(char *buffer_from);


TestDll.cpp

#pragma data_seg(".SHAREDSEG")

// создаём shared-массив, инициализируем первый элемент. остальные
// элементы автоматически проинициализируются тем-же значением.
char SharedString[100] = {0}

#pragma data_seg ()
#pragma comment(linker, "/SECTION:.SHAREDSEG,RWS")

// для синхронизации используем именованный мьютекс
HANDLE g_hMutexSharedString = NULL;

// функция для захвата shared-массива одним процессом
bool LockSharedString(DWORD dwTimeout)
{
     if(g_hMutexSharedString == NULL)
     {
          g_hMutexSharedString = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "MutexSharedString");
          if(g_hMutexSharedString == NULL)
               g_hMutexSharedString = CreateMutex(NULL, FALSE, "MutexSharedString");
     }

     return WaitForSingleObject(g_hMutexSharedString, dwTimeout)
                   == WAIT_OBJECT_0 ? true:false;
}

// функция для освобождения shared-массива
void UnlockSharedString()
{
     ReleaseMutex(g_hMutexSharedString);
}


// Функция для синхронизированного чтения shared-массива
TESTDLL_API bool GetSharedString(char *buffer_to)
{
     if(!LockSharedString(1000)) return false;
     strncpy(buffer_to, SharedString, 100);
     UnlockSharedString();
     return true;
}


// Функция для синхронизированной записи в shared-массив
TESTDLL_API bool SetSharedString(char *buffer_from)
{
     if(!LockSharedString(1000)) return false;
     strncpy(SharedString, buffer_from, 100);
     UnlockSharedString();
     return true;
}

2) Подключаем созданную DLL к тому же проекту TestExe, что и в примере №1, пишем в обработчиках нажатий кнопок Get/Set:
Цитата
void CTestExeDlg::OnButtonGet()
{
     char buffer[100];
     if(GetSharedString(buffer))  // здесь мы читаем из shared-массива
          GetDlgItem(IDC_EDIT1)->SetWindowText(buffer);
}

void CTestExeDlg::OnButtonSet()
{
     char buffer[100];
     GetDlgItem(IDC_EDIT1)->GetWindowText(buffer, 100);
     SetSharedString(buffer);  // здесь мы пишем в shared-массив
}



Для тех, кому лень набирать всё самостоятельно, ниже можно скачать проекты TestExe/TestDll для примера №2:
Автор: mr.DUDA
Сайт: http://






Просмотров: 2292

 

 

Новые статьи:


Популярные:
  1. Как сделать цикличным проигрывание MIDI-файла?
  2. Создание AVI файла из рисунков
  3. Как устройство "отключить в данной конфигурации"?
  4. Kто в данный момент присоединен через Сеть?
  5. Как узнать количество доступной памяти?
  6. Как реализовать в RichEdit разноцветный текст?
  7. Как скрыть свое приложение от ProcessViewer
  8. Как программно нажать/скрыть/показ кнопку "Start"?
  9. Модуль работы с ресурсами в PE файлах
10. Функции вызова диалоговых окон выбора
11. Проверка граматики средствами Word'а из Delphi.
12. Модуль для упрощенного вызова сообщений
13. Функции для записи и чтение своих данных в, ЕХЕ- файле
14. Рекурсивный просмотр директорий
15. Network Traffic Monitor
16. Разные модули
17. Универсальная функция для обращения к любым экспортируем функциям DLL
18. Библиотека от VladS
19. Протектор для UPX'а
20. Еще об ICQ, сообщения по контакт листу?
21. Использование открытых интерфейсов
22. Теория и практика использования RTTI
23. Работа с TApplication
24. Примеры использования Drag and Drop для различных визуальных компонентов
25. Что такое порт? Правила для работы с портами
26. Симфония на клавиатуре
27. Загрузка DLL
28. Исправление автоинкремента
29. Взаимодействие с чужими окнами
30. Проверить дубляжи в столбце


 

 

 
 
На главную