0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Wine原理介紹和開發(fā)教程

深度操作系統(tǒng) ? 來源:深度操作系統(tǒng) ? 2024-12-31 10:06 ? 次閱讀

說起 Wine,稍微資深一點的 Linux 用戶應該都聽過,但是真要說起 Wine 到底是怎么回事,可能大多數(shù)人不見得說得清。這篇文章會簡單地介紹 Wine 的工作原理,以及如何開始 Wine 的開發(fā)。所以如果您屬于以下三類讀者之一:

想?yún)⑴c Wine 開發(fā),但是不知如何開始的。

僅僅想大致了解 Wine 是如何工作的。

只是想能夠愉快的用上最新版本 Wine 的。

希望在看完本文后,能夠有一些收獲。

Part 1 Wine 是什么

Wine 是 "Wine Is Not an Emulator" 的遞歸縮寫,如同 "GNU" 一樣(GNU's Not Unix),字面意思就是 Wine 不是一個模擬器。這里的模擬器主要是指 Wine 并不是一個虛擬機,而是一個 Windows API 實現(xiàn)兼容層。這么說可能不太好理解,大家可以把 Windows 應用程序類比成 Android 應用程序,而 Wine 的角色就和 Android 很像了,將操作系統(tǒng)提供的各種功能封裝成 API,并讓應用程序在隔離的環(huán)境內運行。至于 API 長成啥樣,隔離的力度如何,這些都是實現(xiàn)相關的,和本質并不沖突。另一方面,Wine 其實又是一個模擬器,不過模擬的對象不是硬件 CPU,而是 Windows 的行為。

Part 2 Wine 原理介紹

本節(jié)內容相對來說稍顯基礎和單一啦,并且閱讀時最好對操作系統(tǒng)有一定程度的了解哦。如果只是想編譯、運行,對原理不敢興趣的同學,可以跳過,不影響后面的閱讀。

Wine 的目的是運行 Windows 上的可執(zhí)行程序(PE,portable executable)。我們知道,可執(zhí)行程序的本質其實就是按照某一規(guī)則排列的機器碼,而機器碼是指令集相關的。得益于常見的 PC 機一般是 x86/x64 的,因此 Windows 應用程序從指令集的角度看,是完全可以在 x86/x64 的 Linux 機器上直接運行,而不需要硬件層模擬的。

但是為了能夠直接加載運行 PE 文件,需要滿足一些 ABI 兼容。最基本的,Windows PE 程序會假定自己被加載到地址 0x400000 處,因此 Wine 實現(xiàn)自己的 loader 時,需要保證將 PE 鏡像加載到同樣的位置。對于靜態(tài)鏈接的程序,需要做的事情可能不是太多,但是對于動態(tài)鏈接的程序,Wine 需要模仿 Windows loader 的行為,加載依賴的庫,并進行相應的重定位工作。

為了最大程度上減少對二進制層面的依賴,Wine 決定實現(xiàn)至少 GDI32,KERNEL32,USER32 三個動態(tài)庫,因為其他庫都是建立在這三個庫的基礎之上的。所以理論上來說,除此之外的其他動態(tài)庫是可以直接使用 Windows 上面現(xiàn)有的庫,但由于各種原因,Wine 還是傾向于盡量實現(xiàn)所有的 API。我們把 Wine 自己實現(xiàn)的 API 庫稱作 builtin,把 Windows 上現(xiàn)成的庫稱作 native。當 Wine 在加載 builtin 動態(tài)庫的同時,還會在內存中建立 PE header,用來模仿 Windows 上的內存布局。更加詳細的實現(xiàn),有機會可以寫一篇 Wine loader 相關的文章來介紹 Wine 本身、PE 程序和動態(tài)庫是如何被加載的。

除開 loader 的功能外,Wine 還需要解決進程間通信(IPC)的問題。Wine 的實現(xiàn)方式是將所有跨進程的對象和機制,比如 GDI 對象,比如信號量,全部實現(xiàn)在 Wine server 中。同時 Wine 允許系統(tǒng)運行多個 Wine server 的實例。這樣存在于同一個 Wine server 中的對象自然是可以相互通信,好像在同一個空間內;而不同 Wine server 下的對象,是相互隔離的,這種架構使得不同容器之間的程序相互沒有影響。Wine server 的具體實現(xiàn)是通過 unix socket,實現(xiàn)了一套 IPC 機制,完成和 API 層的交互。

有了以上這些基礎,Wine 實現(xiàn)起各種功能就可以按部就班了,只需理解 Windows 下 API 的行為和含義,然后再重新實現(xiàn)一遍就行了。聽起來雖然簡單,實際難度不小,特別是一些未公開的行為,必須對整體有相當?shù)牧私夂蟛拍芟率帧I踔烈恍┎町?,比?UI 相關的內容,由于 Windows 窗口系統(tǒng)和 X 在設計哲學上的不同,實現(xiàn)上需要有所舍取。目前 Wine 支持的平臺不僅包括 Linux,還包括 BSD、Mac OS X 和 Android。

Part 3 環(huán)境

下面的開發(fā)環(huán)境都以 deepin 為例進行說明。

首先獲取代碼。Wine 官方代碼倉庫地址為

git://source.winehq.org/git/wine.git

如果你想方便打包給別人使用,又不太想折騰打包的一些細節(jié),可以用各個發(fā)行版自己維護的 Wine。比如 Debian 維護的 Wine 倉庫地址為

https://salsa.debian.org/wine-team/wine.git

這里以官方的 Wine 為例:

git clone git://source.winehq.org/git/wine.git

然后安裝開發(fā)的依賴。為了簡單起見,我們只編譯 32 位的 Wine,因為 64 位的 Wine 只支持 64 位的 PE 程序,而目前 Windows 上仍有大量的程序只提供了 32 位的版本。

    sudo apt install
        gcc-multilib
        flex
        bison
        libx11-dev:i386
        libfreetype6-dev:i386
        libxcursor-dev:i386
        libxi-dev:i386
        libxshmfence-dev:i386
        libxxf86vm-dev:i386
        libxrandr-dev:i386
        libxfixes-dev:i386
        libxinerama-dev:i386
        libxcomposite-dev:i386
        libglu1-mesa-dev:i386
        libosmesa6-dev:i386
        ocl-icd-opencl-dev:i386
        libpcap-dev:i386
        libdbus-1-dev:i386
        libgnutls28-dev:i386
        libncurses-dev:i386
        libsane-dev:i386
        libv4l-dev:i386
        libgphoto2-dev:i386
        liblcms2-dev:i386
        libpulse-dev:i386
        libgstreamer-plugins-base1.0-dev:i386
        libudev-dev:i386
        libcapi20-dev:i386
        libcups2-dev:i386
        libfontconfig1-dev:i386
        libgsm1-dev:i386
        libkrb5-dev:i386
        libtiff-dev:i386
        libmpg123-dev:i386
        libopenal-dev:i386
        libldap2-dev:i386
        libxrandr-dev:i386
        libxml2-dev:i386
        libxslt1-dev:i386
        libjpeg62-turbo-dev:i386
        libusb-1.0-0-dev:i386
        gettext
        libsdl2-dev:i386
        libvulkan-dev:i386
接著運行腳本:
./configure --with-gnutls --without-hal --without-oss

根據(jù)不同的 Wine 版本,此時可能會提示不同的 feature 支持情況。我們可以根據(jù)需求,對上面的依賴庫和傳入的參數(shù)進行調整,具體可以查看 configure.ac 的內容。

Wine 的源碼比較大,編譯有些耗時,可以根據(jù) CPU 情況增加并行參數(shù),比如 make -j8,進行編譯。

編譯完成后,運行:

./wine --version
可以查看版本號。如果想安裝到系統(tǒng),可以運行:
sudo make install
但是注意,安裝后可能會修改一些文件的默認打開方式。

Part 4 使用

運行:

./wine winecfg
可以對默認容器進行設置,默認的容器位于 HOME 目錄下的 .wine,環(huán)境變量 WINEPREFIX 用來修改當前的容器路徑。比如有一個叫 demo.exe 的可執(zhí)行文件,我們想測試能否正常運行,可以運行。
WINEPREFIX=~/.demo_exe ./wine demo.exe
HOME 目錄下的`demo_exe`就會作為其容器目錄。

Part 5 開發(fā)

編譯過后的 Wine 源碼目錄結構如下:

    ├── aclocal.m4
    ├── ANNOUNCE
    ├── AUTHORS
    ├── config.log
    ├── config.status
    ├── configure
    ├── configure.ac
    ├── COPYING.LIB
    ├── dlls
    ├── documentation
    ├── fonts
    ├── include
    ├── libs
    ├── LICENSE
    ├── LICENSE.OLD
    ├── loader
    ├── MAINTAINERS
    ├── Makefile
    ├── Makefile.in
    ├── po
    ├── programs
    ├── README
    ├── server
    ├── tools
    ├── VERSION
    └── wine -> tools/winewrapper

目錄 dlls 按照模塊存放了所有 API 的實現(xiàn)。

目錄 loader 是和 Wine 啟動、加載相關的代碼。

目錄 programs 存放了外部程序的代碼,比如注冊表管理工具 regedit 。

目錄 server 顧名思義,是 Wine server 的實現(xiàn)。

接下來需要做的就和普通開發(fā)沒什么兩樣了。比如說我們發(fā)現(xiàn)某個應用存在字體相關的 BUG,可以首先根據(jù)經(jīng)驗判斷在 Windows 上,該程序是如何實現(xiàn)的,然后查看對應的實現(xiàn)。例如 GDI 相關的字體實現(xiàn),位于 dlls/gdi32/font.c 和 dlls/gdi32/freetype.c 。修改完代碼后,在所在模塊的目錄,比如上例就是 dlls/gdi32 下重新 make 就可以快速驗證了。

對于復雜的問題,不太好直接定位的,可以通過輸出日志的方式來調試,環(huán)境變量 WINEDEBUG 指定了需要輸出的日志。

有時我們可能需要把復雜的情況簡單化,這時候難免會寫一些小的 demo 程序來重現(xiàn)問題。如果不想到 Windows 上面編譯,可以使用 mingw 直接在 deepin 下編譯出 exe 文件。方法很簡單,首先安裝 mingw:

sudo apt install mingw-w64
接著正常利用 Windows API 實現(xiàn)程序,最后利用 mingw 編譯工具鏈生成文件即可,Makefile 示例:
hello.exe: hello.c
    i686-w64-mingw32-g++ -o hello.exe hello.c -DUNICODE -D_UNICODE -municode -lgdi32

上面的例子,定義了 UNICODE,所以使用的 UNICODE 版本的 API,入口函數(shù)為 wmain,-lgdi32 表示需要鏈接庫 gdi32 。生成出來的 hello.exe,可以同時在 Windows 和 deepin 下運行。

Part 6 其他

本文介紹的內容只涉及到 Wine 開發(fā)的基礎,Wine 本身還有很多東西值得去探索。比如 Wine 是如何使用 driver 機制讓接口和實現(xiàn)分離的,再比如 Wine 是如何使用純 C 實現(xiàn) COM 機制的。雖然 Wine 的出現(xiàn)已經(jīng)有一些年頭了,但是目前的開發(fā)仍然比較活躍,感興趣的同學可以加入進來,為 Linux 生態(tài)添磚加瓦,讓大家能用到更多的優(yōu)質應用,也算是曲線救國了。

Part 7 更新

7.1 新的 WOW64

上面編譯的例子中,我們只編譯了 32 位的 Wine,忽略了編譯 64 位 Wine 的細節(jié)。從 Wine 8 開始,Wine 開始了一個稱為 PE Convertion 的開發(fā)過程,重新實現(xiàn)了 WOW64 的機制。此模式下只需要編譯出一份 Wine,既可以運行 32 位程序,也能運行 64 位程序。同時也不再依賴 32 位的運行時庫。雖然此模式還被認為處于實驗階段,但是從 deepin-wine8 開始,我們已經(jīng)默認使用此方式。

編譯新的 WOW64 方式的 Wine,步驟如下:

Wine 官方的源碼地址已經(jīng)更改,在https://gitlab.winehq.org/wine/wine.git下載源代碼。

依舊需要安裝編譯時依賴的開發(fā)庫,不同在于我們這次只需要安裝 amd64 的版本,在安裝開發(fā)庫時不再需要指定 :i386 后綴。此外 mingw-w64 在此模式下成為必須項。

在 Wine 源碼目錄的同級目錄下新建 build-wine 目錄,并進入此目錄。

運行 ../wine/configure --prefix=/opt/wine-newwow64 --enable-archs=i386,x86_64。這一步如果有任何提示,比如缺少編譯期依賴,可以在安裝后再次運行。

make -j8,進行編譯。

sudo make install 安裝,Wine 會安裝在第 4 步通過 prefix 指定的位置,即 /opt/wine-newwow64 。當然也可以選擇不安裝,直接在編譯目錄下運行。

7.2 其他架構

在關于原理一節(jié)的描述中我們提到過,x86/x64 機器的 Linux 系統(tǒng)可以通過 Wine 運行 x86/x64 的 PE 程序。實際上如今通過 DBT(dynamic binary translation)技術,在 ARM 及其他架構上已經(jīng)有了運行 Wine 的方案。感興趣的讀者可以查看Box64項目。

11月份,微信在 deepin 商店上架了Linux原生版本,功能與 Windows、MacOS 相差無幾。Wine 版本的微信終于可以"功成身退"了,我們也期待今后有更多軟件推出原生版本,讓 Wine 早點完成"歷史使命"。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    87

    文章

    11312

    瀏覽量

    209711
  • WINDOWS
    +關注

    關注

    4

    文章

    3552

    瀏覽量

    88810
  • 應用程序
    +關注

    關注

    37

    文章

    3277

    瀏覽量

    57737
  • 模擬器
    +關注

    關注

    2

    文章

    877

    瀏覽量

    43254

原文標題:想開啟 Wine 開發(fā)?看這篇就夠了!

文章出處:【微信號:linux_deepin,微信公眾號:深度操作系統(tǒng)】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Wine運行exe軟件的教程

    Linux有很多的軟件,但是在桌面操作軟件生態(tài),還是不如Windows,有些軟件只有Windows版本沒有對應的Linux版本,如果我們想在Linux系統(tǒng)上運行exe程序,就需要借助一些第三方的軟件,下面我就介紹一下用Wine運行exe軟件的教程.
    發(fā)表于 10-10 09:40 ?1.6w次閱讀

    linux下的快捷鍵全面介紹

    輸入剩下的名字。使用tab鍵補全還支持對于擴展名的識別,比如您的文件夾下有”TH2AD_CHS.exe文件和 TH2AD_CHS.ini文件,當您輸入”wine TH”再按下tab后,會補全成
    發(fā)表于 07-09 08:44

    Hi3861 開發(fā)+編譯+燒錄

    燒錄->wine+HiBurn(感謝HonestQiao )開發(fā):燒錄:2、開發(fā)流程首先開發(fā)環(huán)境安裝1.安裝Visual Studio Codehttps
    發(fā)表于 11-12 22:20

    介紹基于協(xié)議棧外設的開發(fā)

    本節(jié)介紹基于芯科協(xié)議棧設備的開發(fā)本節(jié)介紹基于芯科協(xié)議棧外設的開發(fā)
    發(fā)表于 01-07 08:26

    intel edison 開發(fā)板的開發(fā)平臺介紹

    intel edison 開發(fā)板的開發(fā)平臺介紹,以及板載資源的介紹,重量級
    發(fā)表于 10-30 16:12 ?15次下載

    android框架與應用開發(fā)介紹

    android框架與應用開發(fā)介紹
    發(fā)表于 10-24 09:35 ?7次下載
    android框架與應用<b class='flag-5'>開發(fā)</b><b class='flag-5'>介紹</b>

    linux下wine的使用

    Wine 仍在發(fā)展階段,僅能執(zhí)行少部份的 Windows 軟體,大部份的軟體仍然無法正常執(zhí)行。 Wine的官方站點是http://www.winehq.com/,雖然你可以在它的官方站點下載源代碼
    發(fā)表于 11-07 15:37 ?14次下載

    異亮科技發(fā)布新品AIR VALLEY WINE智能凈化落地燈

    異亮科技日前宣布發(fā)布新品 AIR VALLEY WINE智能凈化落地燈,該產品將照明與凈化相結合,顛覆性的提出凈化與照明新概念。AIR VALLEY WINE采用紅酒杯流線型設計理念,機身配備了一鍵式操控,既是開關鍵又擁有調節(jié)風速等功能,設計簡潔干凈。
    的頭像 發(fā)表于 05-21 07:19 ?3008次閱讀

    JEEWeb的開發(fā)相關技術介紹

    本文檔的主要內容詳細介紹的是JEE Web的開發(fā)相關技術介紹
    發(fā)表于 02-15 17:19 ?4次下載
    JEEWeb的<b class='flag-5'>開發(fā)</b>相關技術<b class='flag-5'>介紹</b>

    盤點一下這些可以通過Wine在Linux上玩的游戲

    上古卷軸 5 已經(jīng)不是款新游戲了,但它的 mod 社區(qū)依舊活躍。如果你的 Linux 系統(tǒng)有足夠資源的話,你可以很輕松地加上很多很多 mod。需要記住的是 Wine 運行時要比游戲占用更多的系統(tǒng)資源,所以使用 mod 時也要考慮這一點。
    的頭像 發(fā)表于 04-16 12:41 ?7466次閱讀

    Wine 5.4版本更新更多新功能

    IT之家了解到,WineWine Is Not an Emulator)是一個能夠在多種 POSIX-compliant 操作系統(tǒng)(包括 Linux,Mac OSX 及 BSD 等)上運行 Windows 應用的兼容層。
    的頭像 發(fā)表于 03-14 09:33 ?2357次閱讀

    Wine中將提供Windows應用程序與USB更好支持

    Wine 中運行的 Windows 應用程序直接與 USB 設備交互將會有更好的支持。Wine 項目的提交記錄顯示,最新合并的 WineUSB 初始部分將成為 Wine USB 驅動,類似于微軟的 WinUSB。
    的頭像 發(fā)表于 04-19 09:52 ?2560次閱讀
    <b class='flag-5'>Wine</b>中將提供Windows應用程序與USB更好支持

     Wine更新:支持 Linux 運行 Windows 應用,PE 格式核心模塊

    1月19日消息 外媒 Windows Central 報道,Wine 最近收到了更新,改善了在 Linux 系統(tǒng)上運行 Windows 應用的體驗。該更新以 Win3 6.0 的形式出現(xiàn),根據(jù)其完整
    的頭像 發(fā)表于 01-19 11:49 ?2427次閱讀

    Python語言介紹開發(fā)環(huán)境

    Python語言介紹開發(fā)環(huán)境說明。
    發(fā)表于 04-26 09:51 ?9次下載

    如何在Ubuntu上安裝最新版本的Wine

    新的 Wine 8.0 版本比以往任何時候都更好地支持在 Linux 發(fā)行版(如 Ubuntu)上運行 Windows 應用程序。
    的頭像 發(fā)表于 02-01 10:01 ?6660次閱讀