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

时间:2015-09-01 11:20:22

标签: c++ c linux ipc wine

有没有办法(以及如何)在Linux程序和通过wine运行的Windows程序之间共享内存?

既然很难理解为什么要做这样的事情,我会告诉你我的情况: 我有一个专门为Windows编译的程序,但是这个程序有一个开放的C插件API。但是,我想让我的代码的一部分在本机应用程序上运行(并使用其他库和linux的其他优点),并以快速的方式执行IPC

2 个答案:

答案 0 :(得分:7)

我不确定这是一个好主意,或者它是否可行,但您可以在/dev/shm中创建文件,并从Wine和您的原生Linux应用程序访问它们。

不能保证存在,所以你应该有一个后备IPC方法。

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

否则,您可以尝试构建可以从Linux调用Windows代码的winelib应用程序:http://web.archive.org/web/20150225173552/http://wine-wiki.org/index.php/WineLib#Calling_a_Native_Windows_dll_from_Linux。我也不确定它是否有用。

答案 1 :(得分:6)

Wine的目的是在Unix(类似)系统上提供类似WinAPI的环境。这意味着Wine可以被认为是一个单独的,API独立的“独立”操作系统,位于类Unix系统之上。因此,你说的那台机器实际上可能有两个操作系统,一个在另一个上。首先,“真实”(控制真实硬件)之一,即GNU / Linux。其次,在POSIX / SUS接口之上有称为Wine的WinAPI实现。

而且,就人类而言,只有一种便携式方法可以在具有不同操作系统的机器之间创建进程间通信,而且,正如您可能已经注意到的那样,我指的是套接字。

Wine子系统本身可以被视为半虚拟机,与Linux内核隔离,但同时与它紧密耦合。

为了提高效率,我的建议是将什么套接字与我称之为SHMNP(共享内存网络协议)的套接字一起使用,以提供网络范围的共享内存。再说一遍,记住,两台“机器”(虽然它只是一台机器)应该是独立的。 Wine实现太脏了,不能让笨拙的细节轻松工作(尽管that's nothing compared to Cygwin's hacks)。

SHMNP以这种方式工作。但请注意,SHMNP 存在!这只是理论上的,并且协议结构 et al 没有出于显而易见的原因。

  • 两台机器都创建了自己的套接字/共享内存区域(假设它们先前已经协商了区域的大小)。同时,他们选择一个端口号,其中一台机器成为服务器,另一台成为客户端。连接已初始化。

  • 最初,两台机器中的所有“共享”内存都包含未初始化的数据(另一台机器可能对任何给定的共享内存块具有不同的值)。

  • 在连接关闭之前,如果两台机器中的任何一台机器写入共享内存区域的任何地址,则应将消息发送到另一台机器并显示已更改的信息。 Linux内核的时髦功能可能被利用,甚至允许原始指针与此完美配合(见下文)。但是,我不知道在Windows中这样做,而不是通过专门的ReadNetworkShared()WriteNetworkShared()这样的程序。

  • 实现可能会提供某种同步机制,因此允许网络范围的信号量,互斥量,

Linux内核特有的怪癖: 大多数现代通用硬件体系结构和操作系统提供了一种保护内存免受用户进程的恶意/错误/无意使用的方法。每当您读取/写入未映射到进程的虚拟地址空间的内存时,CPU将通知操作系统内核page fault已发生。随后,内核(如果Unix(类似))将向违规进程发送分段违例信号,或者换句话说,您将收到SIGSEGV。

隐藏的神奇秘密是SIGSEGV可能被捕获并被处理。因此,我们可以mmap()一些内存(共享内存区域),用mprotect()将其标记为只读,然后,每当我们尝试写入共享内存区域中的地址时,该过程将收到SIGSEGV。信号处理程序随后在内核传递的siginfo_t中执行检查,并推断出两个动作之一。

  • 如果共享内存区域中的错误地址abort()或其他。
  • 否则,要写入的页面应复制到临时存储(可能在splice()的帮助下?)。然后,将要写入的页面标记为读/写,并设置一个计时器,以便在超时内将页面再次标记为只读,并且发送旧副本和现在写入页面之间的(可能是压缩的)差异通过套接字(SIMD可能会帮助你)。处理程序然后返回,允许写入(也许,其他写入!)完成,无需进一步干预,直到计时器激活。

每当一台机器通过套接字接收到压缩数据时,它就会被解压缩并写入它所属的位置。

希望这能帮到你!

编辑:我刚刚发现了编辑前设计的一个明显缺陷。如果将(压缩的)页面发送到另一台计算机,则该另一台计算机将无法区分页面中已修改的数据和尚未修改的数据。这涉及竞争条件,接收机器可能丢失尚未发送的信息。但是,一些Linux内核特定的东西修复了它。