Возможно ли, чтобы два EXE-файла получили доступ к одному и тому же объекту в памяти из библиотеки DLL?

#c# #c #windows #dll

Вопрос:

У меня есть требование, при котором двум отдельным приложениям необходимо получить доступ к объекту, содержащемуся в библиотеке DLL, и изменить его (вся логика управления приложением написана на C и работает из библиотеки DLL). Исполняемый файл пользовательского интерфейса (с минимальной логикой, написанный на C ) использует эту библиотеку DLL и взаимодействует с основной библиотекой логики управления. Я хочу добавить дополнительный exe-файл (написанный на C#) для запуска нескольких веб-служб, которым также потребуется доступ к одному и тому же объекту, содержащемуся в DLL.

Комментарии:

1. Все возможно при наличии достаточного количества времени, денег и лептонов.

2. Когда вы говорите «один и тот же объект», должны ли они видеть изменения друг друга или конкретно работать независимо?

3. Библиотека DLL содержит очень большое приложение, с которым exe-файл может взаимодействовать через посредника pub/sub. Мне понадобится доступ к этому объекту брокера из обоих исполняемых файлов, чтобы они могли получить доступ к одним и тем же данным.

4. Ваш вопрос о том, как обмениваться данными между двумя приложениями? Если это так, то общая память может быть одним из подходов, но для этого существует множество способов (очереди, файлы, API и т. Д.). Вы не можете обмениваться данными, загружая общую библиотеку dll.

Ответ №1:

Да, это называется общей памятью. DLL необходимо вызвать CreateFileMapping, чтобы выделить область памяти для совместного использования. Затем вызовите MapViewOfFile, чтобы хорошо … отобразить файл в память. Затем несколько процессов могут получить доступ к этой сопоставленной памяти через ее имя.

Комментарии:

1. Я изучал это, но, насколько я понимаю, вы не можете просто отобразить весь объект в общую память, верно? Данные, генерируемые этим объектом, будут постоянно обновляться и должны быть прочитаны обоими приложениями одновременно.

2. Технически вы можете отобразить весь объект в общую память, если это то, что вы действительно хотите сделать, но это становится немного сложнее, потому что вам нужно изучить формат переносимых файлов Windows, и этот метод обычно используется в «теневых» приложениях. Но я думаю, что вы хотите просто загрузить библиотеку dll и сопоставить ее с памятью.. Это можно сделать и без библиотеки dll, но, по сути, один процесс не может загрузить один и тот же экземпляр библиотеки dll из другого процесса, это будут два отдельных экземпляра

3. Но да, область общей памяти, отображаемая любым процессом или библиотекой dll, может быть доступна другим процессам/библиотекам DLL

Ответ №2:

Это вопрос не о c как таковом, а о том, как ваша операционная система работает с общими библиотеками. Исходя из моего опыта изучения поведения загрузчика приложений в системах Solaris, ответ-нет. Я предполагаю, что за поведением Solaris следуют Windows, Linux и т. Д., Но я полагаю, что может существовать экзотическая операционная система, которая просто хочет, чтобы вы попросили (я смотрю на вас QNX).

В принципе, если вы создадите глобальную переменную, скажем:

 int foo = 5;
 

и скомпилируйте свою библиотеку dll и проанализируйте содержимое вашей библиотеки dll, вы увидите, что foo включен в какой-то раздел данных для чтения/записи.

Поскольку раздел предназначен для чтения/записи, когда exe-файл запускается и загружает dll, операционная система создаст копию этого раздела для exe-файла. Теперь ваш exe-файл может изменить значение на любое значение int, которое он хочет, но он изменяет только свою копию foo.

Если вы запустите другой exe-файл, он тоже загрузит библиотеку dll и тоже получит копию раздела. Этот exe-файл будет иметь собственную копию foo, и изначально он будет установлен на 5.

Разделы только для чтения ведут себя по-другому, поэтому, если бы вы определили foo следующим образом:

 static const int foo = 5;
 

Он окажется в разделе dll, доступном только для чтения, и каждый исполняемый файл будет ссылаться на один и тот же файл в памяти. Это не позволяет вам делать то, что вы пытаетесь сделать, но это приятно знать, так как это экономит память. Хорошее эмпирическое правило состоит в том, чтобы делать все static и const когда это возможно.

Комментарии:

1. Это правильно, но процессы могут обращаться к общей памяти, которая на самом деле не является двумя процессами, использующими один и тот же экземпляр dll. Но это обходной путь

2. Могли бы вы порекомендовать какие-либо альтернативные подходы? -Возможно ли запустить 2 EXE-файла в рамках одного и того же процесса? -Допускает ли дочерний процесс какую-либо степень наследования доступа к памяти? -Было бы хорошей идеей сделать второй exe-файл (в настоящее время фоновая служба) dll и загрузить его из основной библиотеки dll

3. @ScottFraser из того, что я собрал, у вас есть сложная логика, хранящаяся в библиотеке DLL, вы хотите инициализировать объект в библиотеке DLL и использовать этот объект в качестве службы для нескольких дочерних процессов. Почему бы не обернуть объект вокруг API и не выполнить вызовы RPC для взаимодействия с API? Взгляните на gRPC grpc.io .