2016年5月号に寄稿しました。2016年5月号に寄稿しました。2016年5月号(3/24発売。~そのとき、PC上では何が起こっているのか?~」という特集記事を寄稿しました。UWP)の登場背景と基本構造という話を広く書きました*1。Nativeの話なども挟まっていますが、いずれも概要のみです。言語はなぜ動く」というものがあります。これは、Windowsプログラムを含めて様々な言語(JSなど)で書いたプログラムが実際に実行されるまでの流れを解説した、なかなかクールなものでした(私が書いたものではありません)。この流れを一定汲みつつ、よりWindows上そして主にC#で書かれたプログラムへと振ったのが今回の特集です。各分野を専門的にやっている人からするとイントロぐらいの話です。読めて、初心者の方でもなんとなく分かる(そして、更に興味を持って書籍やネットで調べたくなる)というのを狙いにしました。読んでみて「これざっくり把握するのに良いから読んでみて」と後輩へ渡すようなシーンが生まれると最高に嬉しいです。muo.jp宛に指摘を頂けると幸いです。なくなっていましたが、実は一番書きたかったのがこれです。Frameworkの内部やWindowsの内部処理に関する紹介をおこないました。これらのトピックについては、次に挙げる書籍が大変参考になります。なかには入手しにくい本も存在しますが、興味が湧いたらぜひ読んでみてください。Frameworkの構造やCILからネイティブコードへの変換などについて今回の特集では扱いませんでしたが、SOSを利用してJITコンパイル後のx86コードを追いかけるくだりはシビれます。10世代では多少事情が異なるポイントもありますが、原則の部分はほとんど通用します残念ながら絶版本なので、古本在庫が尽きたら異常に値段が上がりそうです。早めに買うことをおすすめしますクラスライブラリのソースコードに迫ってみる内容の割に長かったためかボツになったのがこれです。FrameworkではCLRとクラスライブラリの組み合わせによって実行環境で要求される機能を実現しています。これらの中身にもっと迫ってみることはできないのでしょうか。Frameworkのソースコードを一部MITライセンスという非常に制限の少ない(利用者側の自由度が高い)ライセンスで一般公開しました。この中をたどっていくことで、CLRの実装詳細やクラスライブラリの中身を追いかけることができます。Frameworkが提供する機能のソースコードを追いかける例を紹介します。C#でプログラムを書いていて、プログラムの状態をデバッグ出力することがしばしばあります。Cプログラミングでいうところのprintfデバッグの類です。多く利用される方法はSystem.Diagnosticsパッケージに含まれるDebug.WriteLineメソッドの利用です。この部分はオープンソースで公開されているので、コードを完全に追いかけることができます。試しに追いかけてみましょう。以下の説明でのソースコードはMicrosoft社がMITライセンスにてGitHubで公開しているreferencesourceの抜粋です*2。me!");というコードを書いた場合のクラスライブラリ側コードを追いかけてみます。Debug.WriteLineメソッドはSystem/compmod/system/diagnostics/ディレクトリ以下のDebug.csを起点として呼び出されます。TraceInternalクラスは同ディレクトリにあるTraceInternal.csで定義されています。その中で、呼びだされているWriteLineメソッドは次のとおりです。}ここではロックの取得方法によって処理が2パターンありますが、いずれもListenersからTraceListenerを取り出してそれぞれに対する出力処理をしていることがわかります。同じファイル内を読むと、Listenersはプロパティとして宣言されており、このプロパティを最初に取得するタイミングでデフォルトの内容が作成されることがわかります。ここで実際に生成されるのはDefaultTraceListenerのインスタンスです。DefaultTraceListenerのコードはDefaultTraceListener.csにあります。WriteLineメソッドの中でWriteメソッドを呼び、その中でinternalWriteメソッドを呼び出しています。internalWriteメソッドの記述は次のとおりです。}デバッガでのログ出力が有効であればメッセージをデバッガへ流し、そうでなければSafeNativeMethodsOutputDebugStringメソッドを呼び出しています。この実体はSystem/compmod/microsoft/win32/SafeNativeMethods.csファイルの次の部分です。message);ここでWindows用のDLLへのバインドをおこなう処理が登場しました。APIのリファレンスはhttps://msdn.microsoft.com/ja-jp/library/cc428973.aspxにあります。Frameworkのライブラリは2008年から閲覧専用のライセンスで公開されています*3。Frameworkである4.6.1のソースコードが公開されています。Frameworkでメッセージボックスを表示するプログラムについて、挙動がおかしいとします。その問題を調査したり、フレームワークとの適合度を高めるための用途であれば、ここのソースを読むことができます。コードをコピー&ペーストして利用したり再配布するような行為は禁止されている(GitHubのreferencesourceリポジトリにあるものと違って、ライセンス上の制限がかなり厳しい)ので注意が必要です。ライセンスの全文はhttps://github.com/Microsoft/referencesource/blob/master/LICENSE.txtで公開されています。特集の中では細かな事情として省くことになったのですが、Windowsの構造について話をしていくと避けて通れないのがサブシステムです。Windowsはもともと多様なアーキテクチャの実行ファイルを実行できるように設計されています。Windows向けのexeファイルは素直に実行されますが、たとえばUNIXの仕様に基づくPOSIXサブシステム(以前SFUと呼ばれていたもので、最近のWindowsではSUAと呼ばれます)を利用するものはposix.exeというプロセスがホストする形で実行し、psxdll.dllをライブラリとして利用します。WindowsなのになぜUNIX標準にもとづくプログラムを?と思うかもしれません。これには歴史的な事情があり、1980年代の米国政府が業務に利用するOSの調達要件としてPOSIX.1というUNIX標準への準拠を必須としていたためです。8の時代まで、Enterprise版のWindowsはSUAをサポートしていました。8.1ではSUAが削除されました。代わりにUNIX系の機能をWindows上で利用したい場合にはHyper-Vで仮想化されたUNIX系OSを利用したりCygwinのような仕組みを利用することを推奨するようになりました。Astoriaは、Windows上にAndroidサブシステムを実装してプログラムを実行するという構造をとっていました。これも残念ながら2016年2月にプロジェクトの終了が発表されました。このように、Windowsはシステムコンポーネント次第でさまざまな役割を果たすことができるように設計・実装されてきました(ビジネス的に成功しているかとは別に、このような拡張をおこないやすい内部アーキテクチャというのが肝要です)。補足やセルフツッコミ以下では、もう少し書きたかったけれど紙面の都合上削ることになったものや、少々蛇足で雑誌媒体には合わずカットとなったものなどを挙げていきます。原則的に紙面の各文言へセルフツッコミを入れていく形で書いてみます。テキストかバイナリか的な話でも、テキストエディターで記述したソースコードは、あくまでテキスト形式です。このままでは、コンピュータは実行できません。EICARテストファイルというものがあります(http://www.eicar.org/86-0-Intended-use.html)。これは完全にASCIIの範囲のテキストのみで書かれた、アンチウィルスソフトの動作確認用ファイルです。Modelでないほう)実行形式として正当なものであり、32-bit版のWindowsでは実行可能です(64-bit版のWindowsではCOMファイルを実行できないので、残念ながら最近の多くの環境では実行して試せないのですが)。いう変わり種もありますが、バイナリ芸のエリアですね。フレームワークのくだりWebアプリを作成できるようなライブラリ群を指します。Webアプリに用途を限定しているわけではありません。文の収まりの都合です。コンパイルして実行か逐次実行かというくだりただし、現在のスクリプト言語では、すべてを逐次実行しているわけではありません。プログラムの起動の高速化や、実行速度の改善のために様々な処理を実行前に施しています。いうわけで、JSがJITコンパイルの領域で世界の先端エリアまで行っていたり、PyPyがCPythonより(コード種にもよりますが)何倍も速くコードを実行できる現代に我々は住んでいます。Coreなどでは原則的に事前のCIL生成・アセンブリ生成を捨てて「実行時コンパイルでいいよね?」と来ているわけですし、扱い方の容易さでいうともはやほぼJSです。個人的には、事前コンパイルをおこなって中間言語コード・アセンブリを出力しておく言語群とそれ以外との切り分けは近年ほぼ意味を成さなくなってきていると思っています。runというサブコマンドがあり、実行時に一時ディレクトリでバイナリをビルドしてから実行するスタイルもとれるわけです)。フレームワークについて本文のどの場所というわけではないのですが、フレームワークというフレーズは本当に界隈と人によって持つイメージが違うものです。iOSだとずいぶん小さめの粒度でフレームワーク(framework)という言葉を使います。インポート可能なパッケージの、パッケージングフォーマットというレベルでの利用です。いわゆるシステムフレームワークはかなり大きな規模で切り分けられたものですが、ユーザが好きに作って配布できるフレームワーク(*.framework)はnpmやgemのパッケージレベルです。コラム「corflags.exe」です結局本文では使いませんでしたね。dumpbin.exeで事足りるケースも多いのです。書き換えをしたい時にはcorflags.exeを利用します。いう人も居るので、世の中面白いのです。CILディレクティブとCILオペコードのくだりCILディレクティブは、コンパイラやランタイムによるコードの最適化に利用されます。処理内容ではありません。最適化だけではなくてもちろん.entrypointとか、実行するコードパスを決定するのにも利用されます。SxSマニフェストのくだり.NETアプリのプログラムでは、後述するマニフェスト(SxSマニフェスト)もこのセクションに格納します。SxSマニフェストは.NET固有事情によるものではないのですが、確認した限りはVSからの標準ビルドで常時出力されているのでこのように記載しました。マニフェストたちややこしい話ですが、マニフェストには2種類あります。実際は、まだあります。.NETとWindows界隈、便利な言葉ゆえ「マニフェスト」というのを多用します。DLLへ処理を切り出す動機のくだりDLLが多用される理由は、ライブラリによって勝手に再配布することが許されないものがあるからです。アプリの配布サイズが増えることを許容すればバージョン差異による問題を避けられるのになんで、という話を先回りした話です。Photoshopの内部DLLとかを勝手に同梱して配布したら猛烈に怒られますからね...。DLLにコードを切り出す恩恵つまり、メモリーの節約につながるのですこれは主にシステムコンポーネントの話ですね。ユーザコンポーネントだと、Chromeのように大量のプロセスを生成するプログラムでは恩恵大きいはずですが、普通はせいぜい2-3しかプロセスを立ち上げないのでメリットそこまで大きくありません(無理に切り分けるほどでもないの意)。「ntkrnlpa.exe」ほかにもntkrnlmp.exeやntkrpamp.exeがあります。なんと、このあたりはWikipediaに分かりやすいサポート特性リストがあります(Ntoskrnl.exe)。ntkrnlmp.exeです。CILコードからWindowsのAPI呼び出しまでの話この処理は、CLRの内部でWindowsのMessageBoxWというAPIの呼び出しに変換されています。CLRの内部というのは嘘ではないですが、実際にこの変換をしているのはFX側ですね。このことはソースを参照するとわかります。この部分のコードは残念ながらGitHubのreferencesourceリポジトリには含まれないので、制限付きのほう(前述の、ソースコードを探っていくくだりを参照してください)で読むことになります。APIとは異なる新しいAPIセットが必要だったのです(図1)。導~アプリライフサイクルが大きく違うというのもありますね。なにぶんモバイルではバッテリ消費をおさえやすい構造にする必要があったのだし。タブレットでは、うん。その後にWinRT専用タブレットが消滅したのを見ると、WinRT専用へ振り切るのが早すぎたのは間違いありません。Win32APIの重要度というか、「デスクトップが今まで通りにあってOfficeがこれまで通りウィンドウ状態で動く」というあって然るべきUXを激変させるのがキツかったという話かなと。種類のWindows系OSが存在しました。種類のバイナリファイルを生成してパッケージ内に含めることになります。だいたいx64も別にするので3種類ですけれどね!MIPS増えないかなー(増えない)。MacBookを4/10に注文、4/14出荷、届いたのは4/17だったので正確にはもうすぐ2ヶ月ですが。Dockerで簡単にGPU対応のTensorFlow入りコンテナを作る方法こんにちは。作品群を読んでいたら連休が終わりそうです。重くなるので読み込まないようにすればOK。資料を補足するシリーズです。途中でやったことや、参考情報を書いていきます。