Как разделить память между программой Linux и программой Windows, работающей через Wine (тот же компьютер)?

Есть ли способ (и как) разделить память между программой Linux и программой Windows, работающей через вино?

Поскольку может быть трудно понять, зачем это делать, я расскажу вам свою ситуацию: у меня есть проприетарная программа, скомпилированная только для Windows, но эта программа имеет открытый API-плагин C. Но я хотел бы, чтобы часть моего кода работала в собственном приложении (и использовала другие библиотеки и другие преимущества Linux) и выполняла IPC быстрым способом.


person hl037_    schedule 01.09.2015    source источник
comment
Если вы можете сделать собственный вызов Linux из процессов винных окон, чем вы могли бы использовать shm_open   -  person Serg    schedule 07.08.2016


Ответы (2)


Целью Wine является предоставление WinAPI-подобной среды в Unix-подобных системах. Это означает, что Wine можно рассматривать как отдельную «независимую» операционную систему с API-интерфейсом поверх Unix-подобной системы. Таким образом, эта машина, о которой вы говорите, может фактически иметь две ОС, одну над другой. Во-первых, «настоящая» (управляющая реальным оборудованием), то есть GNU/Linux. Во-вторых, существует реализация WinAPI, известная как Wine, поверх интерфейсов POSIX/SUS.

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

Подсистему Wine можно рассматривать как самостоятельную полувиртуальную машину, изолированную от ядра Linux, но в то же время тесно связанную с ним.

В целях повышения эффективности я предлагаю использовать сокеты what в сочетании с тем, что я называю SHMNP (сетевой протокол с общей памятью), чтобы обеспечить общую память для всей сети. Опять же, помните, обе "машины" (хотя физически это всего лишь одна) должны быть хотя бы независимыми. Реализация Wine слишком грязная, чтобы можно было легко обойти неуклюжие детали (хотя это ничто по сравнению с хаками Cygwin).

SHMNP работает таким образом. Обратите внимание, однако, что SHMNP не существует! Это чисто теоретически, а структуры протоколов et al не представлены по понятным причинам.

  • Обе машины создают свои собственные сокеты/области общей памяти (предполагается, что они заранее согласовали размер области). При этом они выбирают номер порта и одна из машин становится сервером, а другая — клиентом. Соединение инициализировано.

  • Первоначально вся «общая» память на обеих машинах содержит неинициализированные данные (другая машина может иметь другие значения для любого заданного блока общей памяти).

  • Пока соединение не закрыто, если какая-либо из двух машин записывает по любому из адресов области общей памяти, на другую машину должно быть отправлено сообщение с измененной информацией. Причудливые функции ядра Linux могут быть использованы для того, чтобы позволить даже необработанным указателям прекрасно работать с этим (см. ниже). Однако я не знаю, как это сделать в Windows, а не с помощью специализированных ReadNetworkShared() и WriteNetworkShared() подобных процедур.

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

Особенности ядра Linux. Большинство современных аппаратных архитектур общего назначения и операционных систем обеспечивают способ защиты памяти от злонамеренного/глючного/непреднамеренного использования пользовательским процессом. Всякий раз, когда вы читаете/записываете в память, которая не отображается в виртуальном адресном пространстве вашего процесса, ЦП уведомляет ядро ​​операционной системы о ошибка страницы. Впоследствии ядро ​​(если Unix(-подобно)) отправит сигнал нарушения сегментации процессу-нарушителю, или, другими словами, вы получите SIGSEGV.

Скрытый волшебный секрет заключается в том, что SIGSEGV можно перехватить и обработать. Таким образом, мы можем mmap() выделить некоторую часть памяти (общую область памяти), пометить ее как доступную только для чтения с помощью mprotect(), а затем всякий раз, когда мы попытаемся записать адрес в разделяемой области памяти, процесс получит SIGSEGV. Затем обработчик сигнала выполняет проверки в siginfo_t, переданном ядром, и выводит одно из двух действий.

  • Если ошибочный адрес не находится в области общей памяти, abort() или что-то в этом роде.
  • В противном случае записываемую страницу необходимо скопировать во временное хранилище (может быть, с помощью splice()?). Затем отметьте записываемую страницу как чтение/запись и установите таймер, чтобы в течение тайм-аута страница снова была помечена как доступная только для чтения, и была отправлена ​​разница (возможно, сжатая) между старой копией и записанной страницей. через сокет (здесь вам может помочь SIMD). Затем обработчик возвращается, позволяя завершить запись (и, возможно, другие записи!) без дальнейшего вмешательства, пока не сработает таймер.

Всякий раз, когда машина получает сжатые данные через сокет, они просто распаковываются и записываются туда, где они должны быть.

Надеюсь, это поможет вам!

Редактировать: я только что обнаружил очевидный недостаток в дизайне предварительного редактирования. Если (сжатая) страница была отправлена ​​на другой компьютер, этот другой компьютер не смог бы отличить данные, которые были изменены на странице, от данных, которые не были изменены. Это связано с состоянием гонки, когда принимающая машина может потерять информацию, которую она еще не отправила. Тем не менее, некоторые другие вещи, специфичные для ядра Linux, исправляют это.

person 3442    schedule 01.09.2015

Я не уверен, что это хорошая идея и будет ли она вообще работать, но вы можете создавать файлы в /dev/shm и получать к ним доступ как из Wine, так и из вашего родного приложения Linux.

Его существование не гарантируется, поэтому у вас должен быть резервный метод IPC.

https://superuser.com/questions/45342/when-should-i-use-dev-shm-and-when-should-i-use-tmp

В противном случае вы можете попробовать создать приложение winelib, которое может вызывать ваш код Windows из Linux: http://web.archive.org/web/20150225173552/http://wine-wiki.org/index.php/WineLib#Calling_a_Native_Windows_dll_from_Linux. Я тоже не уверен, что это сработает.

person Artur Gaspar    schedule 01.09.2015
comment
Я проголосовал за, так как использовал ваше решение, но я подтвердил другой ответ, потому что он дает больше деталей, которые помогли мне решить использовать файловую систему в памяти, что характерно для этого случая, поскольку вино обращается к файлам через хост libc. - person hl037_; 13.09.2015