wine 如何运行exe 应用

wine 如何运行exe 应用

知道了wine 能够运行Windows 应用以后,一直觉得很奇怪,它是如何调起exe 应用的。下文将详细解释。
在此之前,需要了解下Windows/Linux 分别是如何运行应用程序的。
Windows下可执行文件格式为 PE(Portable Executable),后缀一般为.exe;
Linux下可执行文件格式为 ELF(Executable Linkable Format),无后缀。

下面两幅图分别简要描述了两种格式的区别,如果需要进一步了解两种格式具体的内容,可以查阅官方文档。

  1. PE 格式
    https://learn.microsoft.com/zh-cn/windows/win32/debug/pe-format
    在这里插入图片描述

  2. ELF 格式
    https://refspecs.linuxbase.org/elf/elf.pdf
    在这里插入图片描述

Windows 下运行应用过程

当我们在双击exe 文件时,Windows 系统会执行操作如下:

  1. 创建进程,主线程;
  2. 系统程序检查.exe 文件头;
  3. 连接器嵌入exe 文件头信息;
  4. 导入所需要的dll;
  5. 初始化运行库;
  6. 执行代码中的main 类似入口函数;

Linux 下运行应用程序

当我们在执行Linux 应用时,Linux系统会执行如下操作:

  1. 内核加载映像(≈二进制文件)并看到它是一个动态可执行文件
  2. 内核加载动态加载器(ld.so)并给它控制权
  3. 动态加载器解决依赖关系并加载它们
  4. 动态加载器将控制权交还给原始二进制文件
  5. 原始二进制文件在_start()中开始执行,最终进入main()。

很显然,如果直接执行exe 文件,Linux 系统是不认可的,因为它不是linux 动态可执行文件。每个可执行文件都有定义的一些头文件,里面包含依赖的动态链接库以及运行地址等信息。以一个简单的helloworld 程序为例,编译成Window 版本和Linux 版本以后。均可以通过工具查看到其依赖:

在这里插入图片描述
在这里插入图片描述
那么wine 是如何实现在linux 环境中运行exe 的呢。基于Windows 和Linux 不同的运行流程,wine将Windows可执行文件加载到内存中,解析它,找出依赖关系,找出可执行代码的位置(即.text部分),然后最终跳转到该代码。也即实现了 ld-linux-x86-64.so.2 类似的功能。
理论很简单,实现上确实有较大的难度。难度主要集中在以下几个方面:
1、.text 代码段如何能够在linux 正常运行;
编译生成的机器代码,只要CPU架构是一样的,则意味着其指令集也是一样的,按照逻辑来讲,只要CPU 架构是一致的,是可以正常运行。

2、代码段中涉及系统调用的函数,需要由内核去完成,这时候,应用程序代码需要一种方法来 "中断 "自己,将控制权交给内核(这种操作通常称为上下文切换)。在每个操作系统上,操作系统所暴露的函数集和调用这些函数的方式都是不同的。
Linux上:read, write, open, brk, getpid
Windows上:NtReadFile, NtCreateProcess, NtCreateMutant 。

针对Windows ,可以看如下这幅图,当然,在linux 下同样有用户模式和内核模式的跳转。
在这里插入图片描述
在wine 实现中,在用户层和内核层的接口处,提供ntdll 的自定义实现。在Wine的最新版本中,它由两部分组成:ntdll.dll(PE库)和ntdll.so(ELF库)。第一个部分是一个薄层,只是将调用重定向到ELF对应部分。ELF对应库包含一个名为__wine_syscall_dispatcher的特殊函数,它执行了一个将当前堆栈从Windows转换到Linux并返回的魔术。因此用户调用创建文件 时,就会有如下的调用过程:

CreateFile(kernal) -> NtCreateFile(ntdll.dll) ->NtCreateFile(ntdll.so)
在这里插入图片描述
其中特殊分发函数__wine_syscall_dispatcher 和 __wine_syscall_dispatcher 函数,其实际上是一段针对不同CPU 优化的汇编代码,实现都在针对不同架构处理器的文件中,如:signal_arm.c /signal_arm64.c / signal_x86_64.c /signal_i386.c;

3、Windows 有着众多的dll 和系统API ,并且这些实现是不开源的,可以获取的文档资料也有限制,无法完全去实现部分API;

4、如果有应用(尤其是游戏应用),绕过ntdll,直接调用syscall,那么wine 将无法做到适配。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值