34 ポイント 投稿者 xguru 2022-10-25 | 11件のコメント | WhatsAppで共有
  • Wine は POSIX 互換 OS(Linux、macOS、BSD)で Windows プログラムを実行可能にする互換レイヤー
    • Valve の Steam Deck も Wine ベースのソリューションを使用

WINE = Wine Is Not an Emulator

  • エミュレーター方式は遅く、実際には Linux/macOS は Windows バイナリをネイティブに実行できる(少し手助けすれば)
  • デバッガーを通して Linux/Windows バイナリがどのように動作するかを詳しく説明

Hello, Wine!

  • 基本的に Wine は Windows 実行ファイルに対する「Dynamic Loader」
  • ネイティブの Linux バイナリであり、EXE や DLL をどう処理すべきかを理解している
  • Wine は Windows 実行ファイルをメモリに読み込んだ後、解析して依存関係を把握し、実行すべきコードへジャンプする
  • これだけでもひとまず Windows バイナリを実行可能だが、例外がある

System Calls

  • syscalls と呼ばれるシステムコールが Wine を複雑にしている
  • syscalls は OS に実装されるものであり、実行ファイルやライブラリに入っているものではない
  • OS が提供する syscalls は OS API
    • Linux : read, write, open, brk, getpid,..
    • Windows : NtReadFile, NtCreateProcess, NtCreateMutant,..
  • システムコールはコード内の通常の関数呼び出しとは異なる。たとえばファイルを開く処理は File Descriptor を追跡するため、カーネルで処理されなければならない
  • したがってアプリケーションコードには、自身で「割り込み」をかけてカーネルに制御を渡す方法が必要になる(「Context Switch」)
  • OS が提供する関数群と呼び出し方法は OS ごとに異なる
    • Linux では read() 関数を呼ぶとき、ファイルディスクリプタをレジスタ %rdi に、バッファポインタを %rsi に、読み込むバイト数を %rdx に入れなければならない
    • しかし Windows には read() 関数がカーネル内にない
  • 同じ「Hello World!」を表示するコードを Linux/Windows で実行してみると
    • Linux は libc.so の puts を、Windows は ucrtbase.dll の printf を呼び出す
    • 最近の Linux では静的リンクして puts 実装をバイナリ内に含めてしまい、libc.so が実行時に使われないのが一般的
  • Windows では少なくとも最近までは「システムコールを直接使うのはマルウェアだけだった」
    • 一般的なアプリケーションは常に kernel32.dll/kernelbase.dll/ntdll.dll に依存し、カーネルと直接通信しないようになっている

Runtime translation of Syscalls

  • syscall をインターセプトしたらどうだろう?
    アプリケーションが NtWriteFile() を呼ぶときに割り込み、write() を呼んだあとバイナリが望む結果フォーマットで返してやれば?
  • カスタム版の ucrtbase.dll を提供すれば可能だろうが、複雑な問題が発生する
  • その代わり、バイナリとカーネルの間に挟まっている ntdll.dll を修正する
  • 最近の Wine は ntdll.dll(PE バイナリ)と ntdll.so(ELF バイナリ)で構成される
    • dll は薄いレイヤーで、単に呼び出しを ELF 側へリダイレクトする
    • ELF には __wine_syscall_dispatcher という特別な関数があり、現在のスタックを Windows から Linux、またはその逆へ変換する魔法を行う
  • この syscall dispatcher が Windows の世界と Linux の世界をつなぐ橋になる
    • 呼び出し規約を処理し、スタック領域を確保し、レジスタを移し替えるといった処理を行う
    • 実行が ntdll.so に来て Linux バイナリ側へ渡ると、こちらはすべての Linux API を使えるようになる

これで全部?

  • とても簡単そうに聞こえるが…
    • Windows API は非常に多く、文書化も不十分で、既知・未知のバグがあり、それらをそのまま保存しなければならない。Wine のコードの大半は、さまざまな Windows DLL の実装になっている
    • syscall の呼び出しにはさまざまな方法があり、技術的にはアプリケーションが syscall を直接呼ぶことを防ぐ方法がない
      (Windows ゲームは何でもやることを覚えておこう)
      Linux カーネルにはこれを処理する特別なメカニズムがあり、もちろんこれが複雑さを増している
    • 32bit vs 64bit の問題もナンセンスだ。膨大な数の 32 ビットゲームがあり、それらが再び 64 ビットで再リリースされることはない。Wine は両方をサポートするため、これも複雑さを増している
    • ここでは wine-server についてはまだ触れていない。これは Wine が生成する別プロセスで、カーネルの「状態」(ファイルディスクリプタ、ミューテックスなど)を維持する
    • ゲームを動かしたいなら? DirectX、PulseAudio、入力デバイスなどを処理しなければならず、やることは非常に多い
  • Wine は長年開発されてきて、大きく前進した。今日では Cyberpunk 2077 や Elden Ring のような最新ゲームも問題なく動かせる
    ときには Wine が Windows より優れた性能を見せることさえある

11件のコメント

 
roxie 2022-10-29

内容も内容ですが、要約のクオリティが本当にものすごいですね。ありがとうございます。

 
minho2da 2022-10-25

サブスクリプション型の読書サービスを提供する yes24 と教保文庫を利用しています。

自宅PCの環境をUbuntuに変えてから、Wineを使って YES24 と教保文庫を実行してみました。

どちらも別個のDRMを使っているので動くのかと思いましたが、Qtで作られていると認識している YES24 は問題なく動作し、教保文庫 EBOOK は動きませんでした。(UIは起動、DRMは起動せず)

どちらもDRMが適用されていると思うのですが、何が違って動いたり動かなかったりするのか考えてみたものの、上の記事を読むとだいたい理解できそうですね(「だいたい完全に理解した」画像)

 
bbulbum 2022-10-25

wine5.0以降、カカオトークが何の設定もなしに実行できるようになってうれしいです。(カカオトークを使いたいかどうかとは別として……)
画面表示に多少問題はありますが、クリップボード画像の送信などの機能はシームレスに動作します。
全体としてWineはゲーム実行に注力しているように見えますが、さまざまなアプリもきちんと動かしてくれるので良いですね。
公共機関へのLinux導入の話が出ても、Linux版カカオトークは考えもしないのはちょっと……かなり残念です。
Mac版はあっさり作ったのに……

 
bbulbum 2022-10-25

大まかなことは知っていましたが、こんなに詳しくWineを説明してくれるとは不思議ですね.. w

 
kayws426 2022-10-25

概してWineはWindowsプログラムをうまく実行してくれるので、Wineを使ってクロスプラットフォームアプリを作る、という構想も可能でしょうか?(デスクトップ限定)

 
ganadist 2022-10-26

かなり昔には、ハンコムのHWPもWineベースでLinux向けに移植されて発売されたことがあったと記憶しています。(R4には別個のwin32互換ライブラリレイヤーが入っていて、Wineが使われたのはR5だったか2002だったか、ちょっとあやふやですが)
そのため、一時期はWineのおかげでwin32が最も大衆的で成功したクロスプラットフォームAPIだ、というジョークもありました。
でも今はelectron/wasmの時代ですね;;

 
jinseokim 2022-10-25

少し話は変わりますが、もしそうするのであれば、Wine のライセンスは LGPL であるため、コードの書き方によってはソースコードの一部または全部を公開しなければならない場合があります。

 
kunggom 2022-10-25

原文でも説明されていますが、Wine がエミュレーターではない理由は、CPU 命令をそのまま使うからです。つまり、Wine で動かせるソフトウェアは基本的に x86 または x86-64 CPU 上で動作する Windows 向けソフトウェアだという意味です。

Apple は Mac 全体を ARM アーキテクチャへ移行したうえ、MS でも ARM ベースの開発キット を出している現時点では、x86(-64) ベースの CPU でしか動作しないソフトウェアを「クロスプラットフォーム対応」と呼ぶのは、やや無理があるのではないかと思います。

 
kayws426 2022-10-27

はい。おっしゃる通り……私も気づかないうちにx86系マシンに限定してしまっていたようです。

 
jjpark78 2022-10-25

ElectronやTauriがあるので、クロスプラットフォームを最初から作らなければならないなら、あまり良い選択ではないように思います。 Webブラウザベースの技術を使えない特別な制約があるなら、 クロスコンパイルをしっかりサポートしているQtのようなライブラリを使うほうが良いかもしれませんね..

 
iceflower01 2022-10-25

222