简体   繁体   English

如何在linux程序和运行Wine(同一台计算机)的Windows程序之间共享内存?

[英]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 ? 是否有一种方法(以及如何)在Linux程序和通过wine运行的Windows程序之间共享内存?

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. 由于可能很难理解为什么要做这样的事情,我告诉你我的情况:我有一个仅为windows编译的专有程序,但是这个程序有一个开放的C插件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 但是,我想让我的代码的一部分在本机应用程序上运行(并使用其他库和linux的其他优点),并以快速的方式执行IPC

I'm not sure this is a good idea or if it will even work, but you could create files in /dev/shm and access them both from Wine and your native Linux application. 我不确定这是一个好主意,或者它是否可行,但您可以在/dev/shm创建文件并从Wine和您的本机Linux应用程序访问它们。

It's not guaranteed to exist, so you should have a fallback IPC method. 它不能保证存在,所以你应该有一个后备IPC方法。

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

Otherwise, you might try building a winelib application that can call your Windows code from Linux: http://web.archive.org/web/20150225173552/http://wine-wiki.org/index.php/WineLib#Calling_a_Native_Windows_dll_from_Linux . 否则,您可以尝试构建可以从Linux调用Windows代码的winelib应用程序: http ://web.archive.org/web/20150225173552/http://wine-wiki.org/index.php/WineLib#Calling_a_Native_Windows_dll_from_Linux。 I am also not sure whether it will work. 我也不确定它是否会起作用。

The purpose of Wine is to provide a WinAPI-like environment on Unix(-like) systems. Wine的目的是在Unix(类似)系统上提供类似WinAPI的环境。 This implies that Wine may be considered a separate, API-facaded, "independent" operating system on top and along a Unix-like system. 这意味着Wine可以被认为是一个单独的,API独立的“独立”操作系统,位于类Unix系统之上。 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. 首先,“真实”(控制真实硬件)之一,即GNU / Linux。 Secondly, there is the WinAPI implementation known as Wine in top of the POSIX/SUS interfaces. 其次,在POSIX / SUS接口之上有称为Wine的WinAPI实现。

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. Wine子系统本身可以被视为半虚拟机,与Linux内核隔离,但同时与它紧密耦合。

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. 出于效率目的,我的建议是将什么套接字与我称之为SHMNP(共享内存网络协议)的套接字一起使用,以提供网络范围的共享内存。 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 ). Wine实现太脏了,笨拙的细节很容易被工作 - 虽然这与Cygwin的黑客相比没什么

The SHMNP works this way. SHMNP以这种方式工作。 Note, however, that the SHMNP does not exist! 但是请注意,该SHMNP 存在! 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). Linux内核的时髦功能可能被利用,甚至允许原始指针与此完美配合(见下文)。 I'm, however, not aware of doing it in Windows rather that by specialized ReadNetworkShared() and WriteNetworkShared() -like procedures. 但是,我并不知道在Windows中这样做,而是通过专门的ReadNetworkShared()WriteNetworkShared()类程序。

  • 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. Linux内核特有的怪癖:大多数现代通用硬件架构和操作系统提供了一种保护内存免受用户进程恶意/错误/无意使用的方法。 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. 每当您读取/写入未映射到进程虚拟地址空间的内存时,CPU都会通知操作系统内核发生了页面错误 Subsequently, the kernel (if Unix(-like)) will send a segmentation violation signal to the offending process, or in other words, you receive SIGSEGV. 随后,内核(如果是Unix(类似))将向违规进程发送分段违例信号,或者换句话说,您将收到SIGSEGV。

The hidden magical secret is that SIGSEGV may be caught, and handled. 隐藏的神奇秘密是SIGSEGV可能被捕获并被处理。 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. 因此,我们可以mmap()一些内存(共享内存区域),用mprotect()将其标记为只读,然后,每当我们尝试写入共享内存区域中的地址时,该进程将收到一个SIGSEGV。 The signal handler subsequently performs checks in the siginfo_t passed on by the kernel, and deduces one of two actions. 信号处理程序随后在内核传递的siginfo_t执行检查,并推断出两个动作之一。

  • If the faulty address is not in the shared memory area, abort() or whatever. 如果故障地址不在共享内存区域,则为abort()或其他。
  • Otherwise, the to be written page shall be copied to a temporary storage (maybe with the help of splice() ?). 否则,要写入的页面应复制到临时存储器(可能借助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). 然后,将要写入的页面标记为读/写,并设置一个计时器,以便在超时内将页面再次标记为只读,并且发送旧副本和现在写入页面之间的(可能是压缩的)差异通过套接字(SIMD可能会帮助你)。 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. 每当一台机器通过套接字接收压缩数据时,它就会被解压缩并写入它所属的位置。

Hope this helps you! 希望这对你有所帮助!

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内核特定的东西修复了它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM