Windows 10 RS4におけるWindows Subsystem for Linuxの改良点をチェックする



Windows Info
第112回

2018年01月14日 10時00分更新

文● 塩田紳二 編集● ASCII編集部

 今年3月の完成に向けて、プレビュー版のリリースが進められているWindows 10 RS4だが、昨年最後のBuild 17063では、Windows Subsystem for Linux(以下WSLと表記する)について大きな改良があった。

 RS3ことFall Creators Updateで、正式版となったWSLだが、Windows Serverにも搭載されている。また、Bash on WindowsやBash on Ubuntu on Windowsといった名称が使われていたが、Windows Subsystem for Linuxが正式な名称となり、起動のためのWSLコマンドもサポートされるようになった。

Windows 10 RC4でWindows Subsystem for Linuxが強化
バックグラウンドプロセスが利用可能に

 Build 17063では、「バックグラウンドプロセス」「環境変数の共用」といった機能が実現している。今回はとりあえず概要のみを示し、個々の機能は次回以降に詳しく見ていくことにする。

 「バックグラウンドプロセス」は、このビルドで一気に実装されたのではなく、Build 17017から行われてきた内部改良の結果としてBuild 17063で利用可能となった。

 バックグラウンドで、コンソールを割り当てられていないプロセスは、Build 17046ですでに実行可能だったが、WSLを起動したコンソール(ttyデバイス)を閉じてしまうと、WSL自体が終了してしまうため、バックグラウンドプロセスも終了させられていた。

 しかし、Build 17063からは、バックグラウンドプロセスは、WSLを起動したコンソールを閉じても動作し続けるようになった。これにより、バックグラウンドでネットワーク接続を待って機能提供するようなプログラム(Unix系ではデーモンと呼ぶ。Windowsのサービスに相当)も利用可能になった。たとえば、sshでの接続を受け付けるsshdなどを動作させておくことが可能だ。

 ただし、Linuxの「ランレベル」(rcスクリプト)のような仕組みがないため、デーモンの起動は手動でする必要があり、たとえ複数のデーモンの起動を1つのスクリプトにまとめたとしても、どこかで、root権限で処理するためのsudoコマンド用にパスワードをキーボードから入力しなければならない。

 つまり、Windowsが起動したら自動的にデーモンが起動させることはできず、パスワードを入力するような、なんらかの手作業が必要になる。前述のsshdも「sudo /etc/init.d/ssh」とせねば起動することはできない。しかし、一回起動すれば、Windowsをログオフするか再起動するまでsshdは動き続けることができる。

デーモンはroot権限を必要とする処理を行なうため、起動時にはroot権限でコマンドを実行させるsudoが必要で、パスワードをユーザーが入力しなければならない。一般的なLinuxではスタートアッププロセス(rcスクリプト)内は管理者権限で実行されるため、パスワードの入力は必要ない

 Linuxのお手本となったUnix系OSでは、システムの起動時に特定のスクリプトを管理者権限で実行させることで、デーモンのようなバックグラウンドで動作するプログラムを起動していた。

 そのファイル名からrcスクリプトなどと呼ばれている。Unix SystemV(はAT&Tの商標です、と思わず書きたくなる)では、複数の起動状態を使い分けるためにランレベル(run level)が導入された。起動スクリプトにエラーが起こると、場合によっては復旧に時間がかかってしまうこともあり、エラーの影響を抑えたり、あらかじめ検証した複数の構成から選択して起動できるようにして、エラーに備えるといった仕組みが必要になったからだ。

 その後Linuxでは、こうしたUnixでの取り組みをベースに、ランレベルなどを引き継いだものや、個人向けに簡素化したものなど、さまざまな仕組みが作られた。

 しかし、WSLでは、最初に起動するinitプロセスは、実際にはLinuxのバイナリではなく、Windowsのバイナリであり、Windows環境の中でLinuxのプログラムを動作させるのが目的であったため、ランレベルやrcスクリプトは実装されていない。

 では、WSLのバックグラウンドプロセス実行は、なんの役にも立たないのかというとそうでもない。プログラムに対してちゃんとした環境さえ整えてやれば、ウィンドウを閉じたままでも実行環境を維持することができる。

 たとえば、tmuxのような仮想端末マネージャを使って、複数のシェル環境をウィンドウを閉じても維持しておくことができる。

Windows Insider Preview Build 17063でWSLを起動しtmuxを使って4つのクライアントを動作させている

コンソールウィンドウを閉じるとcmd.exe(Procexp64.exeの下)以下が消えるが、下のtmux、bashのプロセスは残っている

同じくBuild 16299(Fall Creators Update)では、cmd.exe以下のプロセスの構造が少し違うが、下にtmuxやbashのプロセスが並ぶ

コンソールウィンドウを閉じてしまうと、wsl.exeが終了し、下にあったbashやtmuxのプロセスも終了してしまう

 複数のサーバーを管理しているとき、1つのコンソールを切り替えたり、分割ウィンドウからアクセスするなどの操作が可能だ。そんなら相手の数だけコンソールウィンドウを開けばいいじゃないか? と思うかもしれないが、多数の同じようなウィンドウは混同しやすく、一定以上になると間違った操作の原因になりやすい。

 かえって、分割ウィンドウ(tmuxではペインという)を使って位置で対象を区別したり、必要に応じて画面を切り替えて使うほうが頭の中に「全体象」が作りやすく、対象を間違えにくい。ウェブブラウザのマルチウィンドウとタブウィンドウのようなものというと少しわかりやすいだろうか。 なお、tmuxは、ptyがサポートされたRS3から利用可能だったが、プロセスを維持するためには、WSLを起動したコンソールウィンドウを閉じることができなかった。

 もう1つの「環境変数」の共用は、かつて「WSLとWin32の相互運用」(Windows Subsystem for LinuxにおけるWin32相互運用性のメカニズム、本連載の以前の記事を参照のこと)で行なわれた「Path環境変数」の共用をさらに強化したものだ。

 WSLの環境変数の共有では、WSLENVというWin32でもWSLでも見える1つの環境変数に複数の環境変数を区切って格納することで、他方へ環境変数を伝達する。このとき、環境変数の中身に応じたオプションを付け、ファイルパスの変換などを指示することができる。また、WSL側にWin32のパス文字列をDrvfsの形式に変換するwslpathというコマンドが提供されている。

 今回のRS4では、WSL自体が改良されるだけでなく、Windows側にもLinux/Unix)的な機能が導入される。すでにLinux(U)は一定の地位を占め、そのために作られるソフトウェアの中には重要なものも少なくない。しかしWindowsには、独自に開発した部分があり、そのために同じような機能を実現しているLinux/Unix系のAPIを採用しにくい部分があった。

 この部分がオープンソースソフトウェアをWindows上で利用する場合の障害になっていたが、WSLにより、Linuxのバイナリがそのまま実行できるようになった。しかし、WSLの外側にあるWin32は依然として独自の世界のままだ。これでは、WSLとWin32を連携させる場合に問題がある。WSLきWin32相互運用機能は、その解法の1つであり、前述の環境変数の共有もそのためのものだ。

 RS4ではさらに踏み込んで、Windows側にLinux/Unixでよく使われるAPIやコマンドを持ち込み、相互運用を用意にする。たとえば、すでにtarやcurlといったLinux/Unix系のコマンドが搭載された。

 また、APIでも改良がある。Windowsは伝統的にプロセス間通信では「名前付きパイプ(Named Pipe)」という機構を使っている。これに対してLinux/Unix系では、ネットワーク通信に利用するSocketで、プロセス間通信専用のアドレス形式(伝統的な命名に従ってAF_UNIXと呼ばれる。AFはAddress Familyの略)を指定することでプロセス間通信を実現できる(Linux/Unixにも名前付きパイプと呼ばれるAPIはあるが実装としてはWindowsのものと大きく違う)。

 Build 17063から、Windows側のSocketでAF_UNIX形式が利用可能になる。これにより、Linux向けのソフトウェアのプロセス間通信の部分を書き直す必要なく、Windows側で利用できるようになる。ただし、現時点では、あくまでもWin32の中でUnixドメインSocketが利用できるだけだ。

 Windowsに搭載されているSocketは「WinSock」と呼ばれ、マイクロソフトではないところで定義、開発されたものだ。当時のWindows 3.xは、TCP/IPをサポートしていなかった。このため、TCP/IPプロトコルスタックは、サードパーティソフトウェアとして導入されていた。また、アプリケーションの中には、内部に専用のTCP/IPプロトコルスタックを持つものも少なくなかった。これでは、TCP/IPを利用するアプリケーションを開発することが困難だったが、当時のマイクロソフトはインターネットを正しく理解していなかった。

 こうした中、共通のTCP/IPアプリケーションインターフェースとして提案されたのがWinSockだ。これは、BSD系Unixで開発されたSocket(BSD Socket、Barkley Socketともいう)をベースにしたもの。策定にはマイクロソフトの社員も関わったが、最初の提案はサードパーティから行なわれた。その後、マイクロソフトは、Windows95でTCP/IPに対応しWinSockを標準のAPIとして取り込んだ。しかし、WinSockは、そもそもWindowsにTCP/IPプロトコルスタックとの接続インターフェースを作るという目的であったため、プロセス間通信となるAF_UNIXには対応しなかった。

 WindowsがAF_UNIXに対応することで、多くのUnix/Linux向けのソフトウェアのプロセス間通信部分を書き換えることなく利用できるようになる(ソースコードレベルの話だが)。たとえば、Dockerなどの大物ソフトウェアの多くは、そもそもLinux由来であり、UnixドメインSocketを前提に開発されている。現在のDocker for Windowsなどでは、Named Pipeに書き換えられているが、こうした作業は不要になる。また、対応するソフトウェアも少なくないD-BusなどもUnixドメインSocketを利用する。

 最終的にWSL側とWin32側でプロセス間通信ができるようにするならUNIXドメインSocketでなければならない。というのは、WSLは、Linuxのバイナリを動作させることを前提にしていて、WindowsのNamed Pipeに対応するLinuxソフトウェアが開発されることは想定しにくい。



カテゴリートップへ




この連載の記事


こんな記事もよく読まれています



コメントを残す