Wine 与 Linux 内核的交互
Wine 不进内核,也不加载内核模块。Windows 程序以普通 Linux 用户态进程运行;Wine 在用户态把 Windows API / NT syscall 翻译成 Linux 系统调用,或交给 wineserver 做“假内核”对象管理。
总体路径
1. 直接系统调用(最常见)
ntdll的 Unix 层把大量Nt*映射到 Linux syscall / libc:
| Windows 语义 | Linux 侧 |
|---|---|
虚拟内存 |
|
文件 I/O |
|
线程 / 进程 |
|
异常 / 调试相关 |
|
同步(部分) | futex、pipe、eventfd 等 |
信息查询 |
|
特点:同一进程内、能一对一映射的语义,尽量直达内核,延迟低。
2. wineserver:用户态“Windows 内核”
Windows 内核对象(句柄表、Event/Mutex、命名管道、注册表、窗口消息协调、跨进程同步等)在 Linux 上没有对应物,由独立进程 wineserver 实现。
每个 Wine 线程在 TEB 私有数据里挂着与 server 通信的 fd:
wine_server_call()走 Unix socket:发请求、等回复;传 fd 用sendmsg/recvmsg(SCM_RIGHTS)。
wineserver 自己也会调内核,例如:
- 用 ptrace 读写别的 Wine 进程内存(
server/ptrace.c) - 用 epoll/poll、文件、socket、信号管理全局状态
- 读
/proc(server/procfs.c)
可把它理解成:Windows 内核对象管理器在用户态的实现。
3. “Windows syscall” 在 Wine 里是假的
真实 Windows:syscall→ ring0。
Wine:syscall指令被劫持到__wine_syscall_dispatcher,再进ntdll.so的 Unix 实现。
对应用来说像进了内核;对 Linux 来说仍是用户态库调用,必要时再syscall进 Linux。
4. 信号:把内核事件变成 Windows 异常
例如缺页、非法指令:
- 内核发
SIGSEGV/SIGILL/ … - Wine 的
sigaction处理函数转成 NT 异常 / SEH - 再走 Windows 异常分发逻辑
这是 Wine 和内核之间很关键的一条“异步”通道。
5. 其它常见内核接口
- 图形:经 X11/Wayland(用户态协议)或 DRM/
/dev/dri到 GPU 驱动 - 音频:ALSA/Pulse/PipeWire
- 输入:evdev、Wayland 等
- 网络:普通 BSD socket → 内核网络栈
- 设备文件:
/dev/*上的open/ioctl
一张简图
一句话:Wine 与 Linux 内核的交互 = 用户态翻译层(ntdllUnix)直接做系统调用,加上 wineserver 用 IPC + 系统调用模拟 Windows 内核对象。