- How to share memory between linux program and windows program running through Wine (same computer)?
- 2 Answers 2
- Linux — Shared Memory (SHM) (/dev/shm)
- Articles Related
- Management
- File structure
- How to check its size ?
- Limit
- Parameters
- shmmax
- segments
- Process
- top
- Многозадачность в Linux. Язык C. Статья 12. Разделяемая память (shared memory)
- Что такое разделяемая память
- Программа mem4000.c
How to share memory between linux program and windows program running through Wine (same computer)?
Is there a way (and then how to) share memory between a linux program and a windows program running through wine ? Since it could be hard to understand why to do such a thing, I give you my situation : I’ve a proprietary program compiled only for windows, but this program has an open C plugin API. But, I’d like to make part of my code running on a native application (and use other libraries and other advantages of linux), and doing the IPC in a fast way
2 Answers 2
The purpose of Wine is to provide a WinAPI-like environment on Unix(-like) systems. This implies that Wine may be considered a separate, API-facaded, «independent» operating system on top and along a Unix-like system. Thus, that machine you say may actually have two OSes, one over the other. Firstly, the «real» (controlling real-hardware) one, that is, GNU/Linux. Secondly, there is the WinAPI implementation known as Wine in top of the POSIX/SUS interfaces.
And, as far as humankind is concerned, there’s one, and only one single portable way to create inter-process communication between machines with different operating systems, and, as you may have already noticed, I refer to sockets.
The Wine subsystem may be considered a semi-virtual machine by its own right, isolated from the Linux kernel, but tightly coupled to it at the same time.
For efficiency purposes, my proposal is to use what sockets in conjunction with what I call the SHMNP (Shared Memory Network Protocol) to provide network-wide shared memory. Again, remember, both «machines» (although it’s physically just one) shall be though to be independent. The Wine implementation is too dirty for the clumsy details to be easily work-arounded (although that’s nothing compared to Cygwin’s hacks).
The SHMNP works this way. Note, however, that the SHMNP does not exist! It’s just theoretical, and the protocol structures et al are not presented for obvious reasons.
- Both machines create their own sockets/shared-memory areas (it’s assumed they negotiated the area’s size previously). At the same time, they choose a port number and one of the machines becomes the server, the other one becoming the client. The connection is initialized.
- Initially, all «shared» memory in both machines contains uninitialized data (the other machine may have different values for any given shared memory block).
- Until the connection is closed, if any of the two machines write to any of address of the shared memory area, a message shall be sent to the other machine with the information that changed. The Linux kernel’s funky features may be exploited to allow even raw pointers to work perfectly fine with this (see below). I’m, however, not aware of doing it in Windows rather that by specialized ReadNetworkShared() and WriteNetworkShared() -like procedures.
- The implementation may provide some sort of synchronization mechanism, so to allow network-wide semaphores, mutexes, et al.
Linux kernel specific quirks: Most modern general-purpose hardware architectures and operating systems provide for a way to protect memory from malicious/buggy/unintended use by a user process. Whenever you read/write to memory that isn’t mapped in your process’s virtual address space, the CPU will notify the operating system kernel that a page fault has occured. Subsequently, the kernel (if Unix(-like)) will send a segmentation violation signal to the offending process, or in other words, you receive SIGSEGV.
The hidden magical secret is that SIGSEGV may be caught, and handled. Thus, we may mmap() some memory (the shared memory area), mark it as read-only with mprotect() , then, whenever we try to write to an address in the shared memory area, the process will receive a SIGSEGV. The signal handler subsequently performs checks in the siginfo_t passed on by the kernel, and deduces one of two actions.
- If the faulty address is not in the shared memory area, abort() or whatever.
- Otherwise, the to be written page shall be copied to a temporary storage (maybe with the help of splice() ?). Then, mark the to be written page as read/write, and setup a timer so that in within a timeout the page is marked read-only again and the (maybe compressed) difference between the old copy and the now-written page is sent through the socket (SIMD may help you here). The handler then returns, allowing the write (and maybe, other writes!) to complete without further intervention until the timer fires out.
Whenever a machine receives compressed data through the socket, it’s simply decompressed and written where it belongs.
Edit: I just found an obvious flaw of the pre-edit design. If a (compressed) page was sent to another machine, that other machine would be unable to differentiate between data that has been modified within the page and data that hasn’t been modified. This involves a race condition, where the receiving machine may lose information it hasn’t yet sended. However, some more Linux-kernel-specific stuff fixes it.
Linux — Shared Memory (SHM) (/dev/shm)
The shared memory system can also be used to set permissions on memory.
There are two different types of shared memory implementations:
Articles Related
Management
By default, your operating system includes an entry in /etc/fstab to mount /dev/shm .
File structure
shm / shmfs is also known as tmpfs.
tmpfs means temporary file storage facility. It is intended to appear as a mounted file system, but one which uses virtual memory instead of a persistent storage device.
How to check its size ?
To check the size of the shared memory file system, enter the following command:
Limit
To determine current shared memory limits you can use the ipcs command.
------ Shared Memory Limits -------- max number of segments = 4096 max seg size (kbytes) = 1073741824 max total shared memory (kbytes) = 17179869184 min seg size (bytes) = 1
Parameters
shmmax
shmmax define the Maximum size (in bytes) for a shared memory segment.
We gan get the parameters limit by using the proc Filesystem such as:
shmall total shared memory avail: 2097152
segments
------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x45110010 1774485506 oracle 660 1048576 2 0x00000000 3112963 oracle 660 67108864 51 0x00000000 3145732 oracle 660 1543503872 51 0x910ac490 3178501 oracle 660 2097152 51 0x6611c0d9 1774518278 oracle 660 126921994088 1 locked 0x6711c0d9 1774551047 oracle 660 33554432 1 0x1111c0df 1775206408 oracle 660 273722634328 2 locked 0x1211c0df 1775239177 oracle 660 33554432 2
Process
------ Shared Memory Creator/Last-op -------- shmid owner cpid lpid 1774485506 oracle 30581 11420 3112963 oracle 24249 11377 3145732 oracle 24249 11377 3178501 oracle 24249 11377 1774518278 oracle 30572 11420 1774551047 oracle 30572 11420
lpid is the process ID of the last job to attach or detach from the shared memory segment or change the semaphore value.
top
The amount of shared memory used by a task. It simply reflects mem- ory that could be potentially shared with other processes.
Многозадачность в Linux. Язык C. Статья 12. Разделяемая память (shared memory)
Это мой канал Old Programmer программировании и программистах. Тематическое оглавление канала здесь . А тут собраны все ссылки по C/C++. Здесь перечень ссылок на ресурсы, посвященные многозадачности в Linux.
Что такое разделяемая память
Продолжаем рассматривать вопросы, cвязанные с многозадачностью, процессами и их взаимодействием. Сегодня вопрос о разделяемой памяти (shared memory) . Как и ранее, мы программируем на C и в операционной системе Linux.
Если кратко, то суть этой технологии такова:
- Разделяемая память это объект ядра.
- Объект может быть создан и удален.
- Объект создается с некоторым именем, которое может быть использовано другими процессами для доступа к нему.
- Объект можно открыть записать туда и прочесть оттуда. При этом обращение осуществляется по адресу этой области данных.
Для того, чтобы удобно было разбираться с технологией, я разбил всю задачу на четыре подзадачи и написал, соответственно 4 программы ( mem4000.c , mem4010.c , mem4020.c , mem4030.c ).
Программа mem4000.c
Программа создает объект, устанавливает его размер (размер памяти), закрывает объект и заканчивает работу. Объект при этом не уничтожается! Его можно удалить (см. ниже) или он будет удален после перезагрузки системы.
При создании объекта мы используем функцию shm_open :
- 1 — й параметр — имя объекта.
- 2 — й параметр — битовая маска. Она подобрана так, что если объекта нет то он создается для чтения и записи. Если объект есть, то возвращается -1 .
- 3 — й параметр — режим открытия. Он определяет, кто будет иметь право доступа к объекту. Значение это 0777 в числовом выражении и предполагает доступ для всех.
Функция возвращает дескриптор созданного объекта.
Далее используется функция ftruncate , которая устанавливает размер памяти. Первым параметром идет дескриптор объекта, второй параметр — устанавливаемый размер памяти.
gcc mem4000.c -o mem4000 -lrt
Программа mem4010.c очень короткая. По имени объекта разделяемая память функция shm_unlink удаляет этот объект.
gcc mem4010.c -o mem4010 -lrt
В программе mem4020.c объект открывается, получается адрес памяти и пишется туда строка. Обращаю внимание, что у функции shm_open изменилось значение второго параметра. Это и понятно, предполагается, что объект уже создан и его нужно просто открыть, чтобы его использовать.
Функция mmap позволяет получить адрес этой памяти. Она имеет следующие параметры:
- 1-й параметр — обычно всегда 0, что означает, что система сама выбирает адрес памяти
- 2-й параметр — длина области памяти, желаемый режим защиты памяти.
- 3-й параметр. Описывает желаемый режим защиты памяти. Мы предполагаем чтение и запись.
- 4-й параметр — задает тип объекта, принадлежат ли отраженные данные только этому процессу или их могут читать другие. Мы предполагаем, что данные буду читать и другие.
- 5-й параметр — дескриптор объекта.
- 6-й параметр — смещение в разделяемой памяти, т.е. откуда будем читать или куда будем писать.
Если функция выполнилась успешно, то она возвращает адрес куда можно писать или откуда можно читать. В данном случае мы пишем в память.
gcc mem4020.c -o mem4020 -lrt
Программа mem4030.c . Она очень похожа на программу mem4020.c , но читает из разделяемой памяти и сразу выводит на консоль.
gcc mem4030.c -o mem4030 -lrt
Вот и все о разделяемой памяти. Очень удобная вещь в программировании, если вы собираетесь обмениваться данными между разными процессами. В следующих статьях я еще вернусь к разделяемой памяти не много в другом аспекте.
Не забывайте подписываться на мой канал Old Programmer .
Я вижу, что вы забыли поставить ‘ЛАЙК’, не так ли?