Wine 与 Linux 内核的交互

Wine 不进内核,也不加载内核模块。Windows 程序以普通 Linux 用户态进程运行;Wine 在用户态把 Windows API / NT syscall 翻译成 Linux 系统调用,或交给 wineserver 做“假内核”对象管理。

总体路径

1. 直接系统调用(最常见)

ntdll的 Unix 层把大量Nt*映射到 Linux syscall / libc:

Windows 语义Linux 侧

虚拟内存NtAllocateVirtualMemory

mmap/mprotect/munmap/madvise(见dlls/ntdll/unix/virtual.c

文件 I/O

open/read/write/ioctl/fcntl

线程 / 进程

clone/pthread/fork+exec

异常 / 调试相关

sigactionSIGSEGV/SIGILL/… → SEH)

同步(部分)

futex、pipe、eventfd 等

信息查询

/procsysctl

特点:同一进程内、能一对一映射的语义,尽量直达内核,延迟低。


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、信号管理全局状态
  • /procserver/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 内核对象。