<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>dokyouのブログ</title>
<link>https://ameblo.jp/dokyou/</link>
<atom:link href="https://rssblog.ameba.jp/dokyou/rss20.xml" rel="self" type="application/rss+xml" />
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com" />
<description>ブログの説明を入力します。</description>
<language>ja</language>
<item>
<title>Fedora</title>
<description>
<![CDATA[ <span class="filename">Fedora（フェドラ）は、レッドハットが支援するコミュニティー「Fedora Project」によって開発されている、RPM系Linuxディストリビューションである。バージョン6まではFedora Coreと呼ばれていた。特定のバージョンを指す場合は「Fedora 9」のように、バージョン番号を添えて呼ばれることもある。<br><br>Fedoraは、UbuntuやopenSUSE同様、最新の技術を積極的に取り込むディストリビューションとして知られている。また、Fedoraはその開発目的として「rapid progress of Free and Open Source software（フリー／オープンソースソフトウェアの世界を迅速に発展させること）」を謳っており[1]、フリーソフトウェアを厳格に重視したディストリビューションという一面も持っている。<br></span>
]]>
</description>
<link>https://ameblo.jp/dokyou/entry-10543190454.html</link>
<pubDate>Mon, 24 May 2010 00:18:04 +0900</pubDate>
</item>
<item>
<title>ＣＴ・ＭＲＩ</title>
<description>
<![CDATA[ <p>CTはコンピューテッド・トモグラフィ（Computed Tomography）<br>検査機を身体の周りを一周させて、X線をいろんな方向から照射してる。<br>その結果をコンピュータで処理して、立体的な映像を再構成しているのだ。</p><p>MRIはマグネティック・レゾナンス・イメージ（Magnatic Resonance Image）<br>磁場内における核磁気共鳴現象を利用して断面画像を得る方法で、X線CTとはまったく違う。<br>人間の身体を構成してる物質の大部分には水素の原子核が含まれてるんだけど、<br>一定の強さの磁場の中に人体を置くと、この原子核が小さな電磁石みたいになって、同じ方向にスピンするようになる。<br>磁場をなくすと、また元の状態（つまりバラバラな方向にスピンする）になるんだけど、<br>ところが、人体の組織ごとに、元の状態に復帰するまでの時間が違うんだそうな。<br>MRIは人体に磁場を加えてから、水素の原子核の状態が元の状態に戻るまでの時間を測定して、<br>その差をコンピュータで立体映像にしているのだ。そうすると、不思議なことに内蔵とか血管とかの映像ができあがるんだって。</p><p><br>広義のCTには他にもPET（ポジトロン断層法）とか SPECT（単一光子放射断層撮影）なんてのもあって、<br>今もどんどん改良が進んでるんだとか。</p>
]]>
</description>
<link>https://ameblo.jp/dokyou/entry-10499374631.html</link>
<pubDate>Sun, 04 Apr 2010 01:45:02 +0900</pubDate>
</item>
<item>
<title>粒子・原子・分子</title>
<description>
<![CDATA[ <p>粒子：物質をつぶとして見たときの構成物<br>分子：物質が物質としての性質を維持できる最小の単位粒子<br>原子：物質を構成する元素としての最小の粒子</p><p>あたりが、適当な定義ではないかと思います。</p><p>但し、原子ですら、最小粒子（素粒子）ではありません。<br>原子は、陽子、中性子、電子で出来ていますし、陽子、中性子もクォークから<br>できているというのが現状の素粒子論です。<br>最新では、物質の根元はヒモである、という理論もあります。</p><p><br>陽電子（ポジトロン、positron）は、電子の反粒子。<br>絶対量が電子と等しいプラスの電荷を持ち、<br>その他の電子と等しいあらゆる特徴（質量やスピン角運動量 (1/2)）を持つ。</p>
]]>
</description>
<link>https://ameblo.jp/dokyou/entry-10499374320.html</link>
<pubDate>Sun, 04 Apr 2010 01:44:24 +0900</pubDate>
</item>
<item>
<title>第3回 .NETアプリケーションが実行される仕組み</title>
<description>
<![CDATA[ <p>　<a href="http://www.atmarkit.co.jp/fdotnet/dotnetwork/dotnetwork02/dotnetwork02_01.html">前回</a> は、Windows OS上で.NETアプリケーションが起動する仕組みとして、.NETアプリケーションがWin32アプリケーションとして動作している部分の処理の流れを説明した。そしてそのWin32の世界から.NETの世界への入り口として、最終的にmscoree.dllの_CorExeMain関数が呼び出されることが分かった。</p><p>　今回はこの_CorExeMain関数から、どのようにして.NETアプリケーションが、その実行環境である（.NET Frameworkの）<a href="http://www.atmarkit.co.jp/icd/root/90/14096290.html">CLR（Common Language Runtime：共通言語ランタイム）</a> 上で動作し始めるのか、その仕組みを解説する。具体的には、</p><ul><li>「mscoree.dllの_CorExeMain関数」から </li></ul><p align="center">↓</p><ul><li>「.NETアプリケーションの次のMainメソッドのコード（C#）」まで<br><code>static void <b>Main</b>() <br>{<br>Application.Run(new Form1());<br>}</code> </li></ul><p>の実行ステップを明らかにする。</p><p>　本稿では前回と同じ、次のようなシンプルなWindowsアプリケーション（WindowsApplication1.exe）をサンプルとして使用する。この.NETアプリケーションが、CLR上で起動する際の処理の流れをつぶさに追いかける。</p><table cellspacing="0" width="407" align="center" bgcolor="#e7e3e7" border="0"><tbody><tr align="center"><td><img style="WIDTH: 350px; HEIGHT: 356px" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fdotnetwork%2Fdotnetwork03%2Fdotnetwork03_01.gif"></td></tr><tr><td><font size="2"><b>本稿で使用するサンプル・アプリケーション</b></font></td></tr><tr><td><font size="2">本稿では、「WindowsApplication1.exe」というシンプルなWindowsアプリケーションをサンプルとして使用する。この.NETアプリケーションが、CLR上で起動するときの処理の流れを解説する。</font></td></tr><tr><td><table cellspacing="0" width="100%" border="0"><tbody><tr><td width="13"> </td><td valign="top" width="10"><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F01.gif" width="16"></td><td><font size="2">エクスプローラに表示されている「WindowsApplication1.exe」をダブルクリックする。</font></td></tr><tr><td width="13"> </td><td valign="top" width="10"><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F02.gif" width="16"></td><td><font size="2">Windows OSのデスクトップ画面上に、「Form1」というタイトルでアプリケーション・ウィンドウが表示される。</font></td></tr></tbody></table></td></tr></tbody></table><p>　それでは_CorExeMain関数以降の実行処理の流れに入っていきたいが、その前提知識としてあらかじめ.NETプログラムの内部構造について知っておいた方が理解が早い。そこで本稿では、まずこの.NETプログラムの構造について概説しておくことにしよう。</p><p>　なお本稿で提示されている図版などは簡略化しており、内部構造のすべてを詳細かつ正確に明記しているわけではないことをあらかじめお断りしておく。</p><h4>.NETプログラムの構造（箱と本体）</h4><p>　.NETプログラムはWindows上の「ファイル」に格納されており、そのファイルはWindows OS（Win32システム）が認識可能な「PE（Portable Execute）フォーマット」である、と<a href="http://www.atmarkit.co.jp/fdotnet/dotnetwork/dotnetwork02/dotnetwork02_01.html#exefile">前回</a> 説明した。</p><p>　当然ながら.NETプログラムの実体となるコードも、このPEフォーマットにのっとってファイル内部に格納されているはずだ。それではその内部構造はどのようになっているのだろうか。</p><p><b>●.NETプログラムにおけるPEフォーマットの構造</b></p><p>　そこで、その内部構造を（簡略化して）示したものが次の図と表である。</p><table cellspacing="0" width="486" align="center" bgcolor="#e7e3e7" border="0"><tbody><tr align="center"><td><img style="WIDTH: 350px; HEIGHT: 342px" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fdotnetwork%2Fdotnetwork03%2Fdotnetwork03_02.gif"></td></tr><tr><td><font size="2"><b>（.NETプログラムにおける）PEフォーマットの構造</b></font></td></tr><tr><td><table border="0"><tbody><tr bgcolor="#000066"><td><font size="2"><b><font color="#ffffff">項目</font></b></font></td><td><font size="2"><b><font color="#ffffff">説明</font></b></font></td></tr><tr bgcolor="#e7e3e7"><td valign="top"><font size="2"><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F01.gif" width="16" align="absMiddle"> PEヘッダ</font></td><td><p><font size="2">＜Win32プログラム＞のエントリ・ポイントへのアドレスなどが</font></p><p><font size="2">格納されている。前回で解説済み</font></p></td></tr><tr bgcolor="#ffffff"><td valign="top"><p><font size="2"><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F02.gif" width="16" align="absMiddle"> Win32プログラム</font></p><p><font size="2">・コード</font></p></td><td><p><font size="2">＜.NETプログラム＞のエントリ・ポイントへのジャンプ命令が</font></p><p><font size="2">格納されている。具体的なジャンプ先は、 mscoree.dllの_</font></p><p><font size="2">CorExeMain関数か、もしくは_CorDllMain関数である。</font></p><p><font size="2">これについても前回で解説済み</font></p></td></tr><tr bgcolor="#e7e3e7"><td valign="top"><font size="2"><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F03.gif" width="16" align="absMiddle"> CLRヘッダ</font></td><td><p><font size="2">「CLI（Common Language Infrastructure）ヘッダ」とも呼ばれる。</font></p><p><font size="2">CLRデータに関するヘッダ情報として</font></p><p><font size="2">「<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F05.gif" width="16" align="absMiddle"> マニフェスト」が格納されている</font></p></td></tr><tr bgcolor="#ffffff"><td valign="top"><font size="2"><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F04.gif" width="16" align="absMiddle"> CLRデータ</font></td><td><p><font size="2">「CLIデータ」とも呼ばれる。.NETプログラムの実体として</font></p><p><font size="2">「<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F06.gif" width="16" align="absMiddle"> 型メタデータ」「<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F07.gif" width="16" align="absMiddle"> ILコード」「<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F08.gif" width="16" align="absMiddle"> マネージ・リソース」が</font></p><p><font size="2">格納されている</font></p></td></tr></tbody></table></td></tr><tr><td><p><font size="2">ここで示した内部構造は分かりやすくするために簡略化して表したものなので、</font></p><p><font size="2">厳密な構造（および位置関係、順序）ではないことに注意すること。</font></p><p><font size="2">なお<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F05.gif" width="16" align="absMiddle">～<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F08.gif" width="16" align="absMiddle">については後述する。</font></p></td></tr></tbody></table><p>　上記の図表で「.NET用」と記述されている<font size="2"><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F03.gif" width="16" align="absMiddle"></font>CLRヘッダと<font size="2"><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F04.gif" width="16" align="absMiddle"></font>CLRデータを組み合わせたものが、「.NETプログラムの本体」だと見なすことができる。従って.NETの世界から見ると、PEフォーマットは.NETプログラム本体を収納するための「箱（＝ケース、入れ物）」でしかない。</p><p>　.NETの世界では、この箱と.NETプログラムの本体を含む物理的なファイル（もしくは、それをメモリ上にロードした後のデータ）のことを「マネージ・モジュール」（Managed Module。以降、モジュール）と呼んでいる。また、.NETプログラム本体のことは「アセンブリ」（Assembly）と呼んでいる（ちなみに.NETにおけるアセンブリは、Windows XPのサイド・バイ・サイド機能で使われる「<a href="http://www.atmarkit.co.jp/fwin2k/techreview/wininstaller/wininstaller07.html">Win32 アセンブリ</a> 」という用語と区別するために、「.NETアセンブリ」と表記されることがある）。</p><p>　実はアセンブリは、「個々のファイル」という物理的な単位ではなく、「1つ以上のモジュール（＝ファイル）の集合体」という論理的な単位で（.NETによって）とらえられる。つまり、Windows世界のアプリケーションの最小単位がモジュール（＝個々のファイル）であるのに対し、.NET 世界のアプリケーションの最小単位はアセンブリ（＝1つのファイルで構成されるときと複数のファイルで構成されるときがある）なのだ。</p><p>　このため.NETでは、複数のモジュール（＝ファイル）を寄せ集めて1つのアセンブリを構築できる。このようなアセンブリは「マルチ・モジュール・アセンブリ」（Multi-Module Assembly。もしくは「マルチ・ファイル・アセンブリ：Multi-File Assembly」。以降、MMA）と呼ばれる。ただし、このMMAはVisual Studioのデフォルト機能では作成できないため、実際にMMAのアプリケーションを構築することはそれほど多くないようだ。</p><p>　ほとんどの.NETプログラムは、「1モジュール＝1アセンブリ」の「シングル・モジュール・アセンブリ」（Single-Module Assembly。もしくは「シングル・ファイル・アセンブリ：Single-File Assembly」。以降、SMA）である。</p><p>　そこで本稿では、このSMAについてのみ解説していく。MMAについての詳細は、「<a href="http://www.microsoft.com/japan/msdn/library/ja/cpguide/html/cpconcontentsofassembly.asp" target="_blank">MSDN：アセンブリの内容</a> 」を参照していただきたい。</p><p><b>●.NETプログラム本体の構造</b></p><p>　次の図と表は、.NETプログラム本体（＝SMA）の内部構造を示したものである。以降の解説で基礎知識として必要になるので、表内の説明もざっと一読してほしい。</p><table cellspacing="0" width="486" align="center" bgcolor="#e7e3e7" border="0"><tbody><tr align="center"><td><img style="WIDTH: 350px; HEIGHT: 341px" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fdotnetwork%2Fdotnetwork03%2Fdotnetwork03_03.gif"></td></tr><tr><td><font size="2"><b>.NETプログラム本体の構造</b></font></td></tr><tr><td><table border="0"><tbody><tr bgcolor="#000066"><td width="20%"><font size="2"><b><font color="#ffffff">項目</font></b></font></td><td><font size="2"><b><font color="#ffffff">説明</font></b></font></td></tr><tr valign="top" bgcolor="#e7e3e7"><td><font size="2"><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F05.gif" width="16" align="textTop">マニフェスト</font></td><td><p><font size="2">「アセンブリ・メタデータ」とも呼ばれる。メタデータとは、</font></p><p><font size="2">一般的には「データのためのデータ」のことである。</font></p><p><font size="2">つまりここには、</font></p><p><font size="2">データであるアセンブリ（＝.NETプログラム本体）に関する</font></p><p><font size="2">データ（情報）が格納されている。</font></p><p><font size="2">ここで管理される情報には、例えば<br><br></font><font size="2"><b>・ランタイム・バージョン（runtime version）<br></b>　……実行するCLRのバージョン<br><b>・メタデータ（MetaData）のアドレスとサイズ<br></b>　……<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F06.gif" width="16" align="absMiddle">型メタデータの場所<br><b>・フラグ（flags）<br></b>　……（不必要なネイティブ・コードが含まれない）純粋な</font></p><p><font size="2">ILコードであるかどうか（＝COMIMAGE_FLAGS_ILONLY）や</font></p><p><font size="2">厳密名（＝電子署名）があるかないか</font></p><p><font size="2">（＝COMIMAGE_FLAGS_STRONGNAMESIGNED）などの</font></p><p><font size="2">情報<br><b>・エントリ・ポイント・トークン（entry point token）<br></b>　……<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F06.gif" width="16" align="absMiddle">型メタデータのテーブル上にある</font></p><p><font size="2">エントリ・ポイント（Mainメソッド）のキー番号<br><b>・リソース（Resources）のアドレスとサイズ<br></b>　……<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F08.gif" width="16" align="absMiddle">マネージ・リソースの場所<br><b>・厳密名シグネチャ（StrongNameSignature）の</b></font></p><p><font size="2"><b>アドレスとサイズ<br></b>　……厳密名の場所</font><font size="2"><br><br>などがある（「……」の後ろに書かれているのは、</font></p><p><font size="2">その情報から分かること）</font></p></td></tr><tr valign="top" bgcolor="#ffffff"><td><font size="2"><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F06.gif" width="16" align="absMiddle">型メタデータ</font></td><td><p><font size="2">単に「メタデータ」と呼ぶ場合はこれを指す。</font></p><p><font size="2">ここには主に、「アセンブリ内で＜定義＞されている、</font></p><p><font size="2">型（クラスなど）とそのメンバに関する情報」と</font></p><p><font size="2">「アセンブリ内で＜参照＞している、型とメンバに</font></p><p><font size="2">関する情報」という2種類の型メタデータ・テーブルが</font></p><p><font size="2">格納されている</font></p></td></tr><tr valign="top" bgcolor="#e7e3e7"><td><font size="2"><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F07.gif" width="16" align="absMiddle">ILコード</font></td><td><p><font size="2">「マネージ・コード」とも呼ばれる。ここには実際の</font></p><p><font size="2">.NET用のプログラム・コードが格納されている。</font></p><p><font size="2">このコードは、特定のCPUやプラットフォームに</font></p><p><font size="2">依存しない抽象化された中間コードなので、</font></p><p><font size="2">IL（Intermediate Language：中間言語）コードと</font></p><p><font size="2">命名されている。なおILコードには、汎用フォーマットの</font></p><p><font size="2">「CIL」（Common Intermediate Language）と</font></p><p><font size="2">マイクロソフトが提供する拡張フォーマットの</font></p><p><font size="2">「MSIL」（Microsoft Intermediate Language）の</font></p><p><font size="2">2種類がある。Visual Studioや.NET Framework</font></p><p><font size="2">付属のコンパイラで生成したプログラムはMSILである</font></p></td></tr><tr valign="top" bgcolor="#ffffff"><td><font size="2"><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F08.gif" width="16" align="absMiddle">マネージ・リソース</font></td><td><p><font size="2">マネージ・リソース（Managed resources）には、</font></p><p><font size="2">ビットマップや文字列などの（.NETにより管理された）</font></p><p><font size="2">リソースが格納されている</font></p></td></tr></tbody></table></td></tr></tbody></table><p>　以上、.NETプログラムの構造として「箱であるモジュールの構造」と「本体であるアセンブリの構造」を説明した。それでは、本題である.NET プログラムの実行処理の流れを順に追っていくことにしよう。</p><br><h4>.NETプログラム実行の処理の流れ（Mainメソッドまで）</h4><p>　次の図は、冒頭で示したサンプル・アプリケーション（.EXEファイル）をダブルクリックして起動したときの、CLR上での処理の流れ、具体的には_CorExeMain関数を呼び出してから後の処理の流れを図示したものである。ちなみに_CorDllMain関数の場合も以下の流れと大差ない。</p><p></p><table cellspacing="0" width="486" align="center" bgcolor="#e7e3e7" border="0"><tbody><tr align="center"><td><img style="WIDTH: 350px; HEIGHT: 342px" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fdotnetwork%2Fdotnetwork03%2Fdotnetwork03_04.gif"></td></tr><tr><td><p><font size="2"><b>CLR上で.NETアプリケーションが起動する際の処理の流れ図</b></font></p><p><font size="2"><b>（Mainメソッドまで） </b></font></p></td></tr><tr><td><p><font size="2">ディレクトリ（本稿の例では「C:\fdotnet\WindowsApplication1\bin \Release」）</font></p><p><font size="2">の中にあるWindowsアプリケーション「WindowsApplication1.exe」を</font></p><p><font size="2">ダブルクリックして実行したときの CLR上での処理プロセスを図示したもの。</font></p><p><font size="2">CLRに処理が引き渡される前の、つまり_CorExeMain関数が</font></p><p><font size="2">呼び出される前までの処理の流れについては前回の</font></p><p><font size="2">「<a href="http://www.atmarkit.co.jp/fdotnet/dotnetwork/dotnetwork02/dotnetwork02_01.html">.NET アプリケーションが起動する仕組み</a> 」を併せて参照するとよい。</font></p></td></tr><tr><td><table cellspacing="0" width="100%" border="0"><tbody><tr><td width="13"> </td><td valign="top" width="10"><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F01.gif" width="16"></td><td><font size="2">「CLRの初期化処理」と「CLRローダーの始動」。</font></td></tr><tr><td width="13"> </td><td valign="top" width="10"><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F02.gif" width="16"></td><td><font size="2">＜アセンブリ・ローダー＞による「アセンブリのロード」。</font></td></tr><tr><td width="13"> </td><td valign="top" width="10"><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F03.gif" width="16"></td><td><font size="2">＜ポリシー・マネージャ＞による「厳密名の検証」。</font></td></tr><tr><td width="13"> </td><td valign="top" width="10"><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F04.gif" width="16"></td><td><font size="2">CLRローダーによる「MainメソッドのILコード上の位置の特定」。</font></td></tr><tr><td width="13"> </td><td valign="top" width="10"><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F05.gif" width="16"></td><td><p><font size="2">＜クラス・ローダー＞による「Mainメソッド呼び出しに</font></p><p><font size="2">必要な型情報の収集」。</font></p></td></tr><tr><td width="13"> </td><td valign="top" width="10"><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F06.gif" width="16"></td><td><font size="2">CLRローダーによる「Mainメソッドの呼び出し」。</font></td></tr><tr><td width="13"> </td><td valign="top" width="10"><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F07.gif" width="16"></td><td><font size="2">＜JITコンパイラ（型ベリファイア）＞による「型の妥当性検証」。</font></td></tr><tr><td width="13"> </td><td valign="top" width="10"><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F08.gif" width="16"></td><td><font size="2">＜JITコンパイラ＞による「ILコードからネイティブ・コードへの変換」。</font></td></tr><tr><td width="13"> </td><td valign="top" width="10"><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F09.gif" width="16"></td><td><font size="2">＜コード・マネージャ＞による「ネイティブ・コードの実行と管理」。</font></td></tr></tbody></table></td></tr></tbody></table><p></p><p>　それでは、ここで図示されている一連の処理の流れを、1つずつ、もう少し詳しく説明していこう。</p><p><b>●<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F01.gif" width="16">「CLRの初期化処理」と「CLRローダーの始動」</b></p><p>　<a href="http://www.atmarkit.co.jp/fdotnet/dotnetwork/dotnetwork02/dotnetwork02_02.html#dotnetentry">前回の最後</a> で説明したように、mscoree.dllの_CorExeMain関数（プログラムが.EXEファイルの場合。.DLLファイルの場合は_CorDllMain関数）が「.NET世界の玄関口となる<a href="http://www.atmarkit.co.jp/icd/root/57/5787157.html">API</a> 」である（ちなみに「mscoree」は、「MicroSoft Component Object Runtime Execution Engine：マイクロソフト・コンポーネント・オブジェクト・ランタイム実行エンジン」の略である）。</p><p><b>（1）CLRの初期化処理</b></p><p>　_CorExeMain関数の内部では、まずCLRの初期化処理が行われる。具体的には、アセンブリのCLRヘッダ（マニフェスト）を解析して、そのアセンブリが対応しているCLRバージョン（＝ランタイム・バージョン）を特定する。このときにもし、肝心のマニフェストがアセンブリに格納されていなければ、そこで例外が発生してプログラムの実行は終了する。</p><p>　なおCLRにはすでにいくつかのバージョンがリリースされているが、ここで特定したバージョンのCLRがローカル環境にインストールされていない場合には、別バージョンのCLRが代理として自動的に使用されることがある。例えば、特定したアセンブリのCLRバージョンが「1.0.3705」（＝.NET Framework 1.0でビルドした場合）で、ローカル環境のCLRバージョンが「1.1.4322」の場合、自動的にバージョン「1.1.4322」のCLRが用いられる。</p><p>　ちなみに、アセンブリのCLRバージョンが「1.1.4322」（＝新しいバージョン）で、ローカル環境のCLRバージョンが「1.0.3705」（＝古いバージョン）の場合は、古いバージョンのCLRは使用されずにプログラムは終了する。つまり新しいCLRバージョンのアセンブリを古い環境で実行することは基本的にできない。</p><p>　また、アプリケーション構成ファイル（.configファイル）を使ってサイド・バイ・サイド（side-by-side）実行が指定されている場合には、その構成ファイル内で指定されたCLRバージョンが使用される。CLRのサイド・バイ・サイド実行については「<a href="http://www.atmarkit.co.jp/fdotnet/dotnettips/350sidebyside1/sidebyside1.html">TIPS：サイド・バイ・サイドによりCLRバージョンを指定するには？</a> 」を参照してほしい。</p><p>　以上の手順によりCLRバージョンが決定したら、いよいよCLRの実行エンジン（以降、「CLRローダー」）が動作する。</p><p>　なお、実はmscoree.dllの仕事範囲は、CLRローダーを動作させる前までのつなぎでしかない。それ以降の本格的なCLRの処理は、ほかの.DLLファイル（例えばmscorwks.dllやmscorsvr.dllなど）に処理が引き継がれる。このためmscoree.dllは、「CLRの詰め木（シム）」を意味する“CLR Shim”と呼ばれることがある。</p><p><b>（2）CLRローダーの始動</b></p><p>　CLRローダーを動かすために、（<a href="http://www.microsoft.com/japan/msdn/library/ja/cpgenref/html/grfuncorbindtoruntimeex.asp" target="_blank">CorBindToRuntimeEx関数</a> というWin32 APIを呼び出して）決定したバージョンのCLRローダーを、ホスト・<a href="http://www.atmarkit.co.jp/icd/root/78/5787378.html">プロセス</a> （＝現在プログラムを実行中のプロセス）に読み込む。これによってCLRローダーが動き始める。</p><p>　さらにこの際、デフォルト（＝既定）のアプリケーション・ドメイン（＝.NET専用のプロセス）が自動的に作成される。</p><p><b>●<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F02.gif" width="16">CLRローダーの＜アセンブリ・ローダー＞による「アセンブリのロード」</b></p><p>　動作し始めたCLRローダーはアセンブリ・ローダー（Assembly Loader）によって、（<a href="http://www.microsoft.com/japan/msdn/library/ja/cpref/html/frlrfSystemAppDomainClassLoadTopic.asp" target="_blank">System.AppDomainオブジェクトのLoad メソッド</a> という.NET APIを活用して）既定のアプリケーション・ドメインの中にアセンブリをロード（＝展開）する。</p><p>　これにより、以降のアセンブリ（＝プログラム本体）のすべての実行処理は、.NETの世界で進められることになる。要するにここで初めて実行環境の舞台が、Win32世界（Windowsローダー）から.NET世界（CLRローダー）に完全に遷移したといえるだろう。</p><p><b>●<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F03.gif" width="16">CLRローダーの＜ポリシー・マネージャ＞による「厳密名の検証」</b></p><p>　アセンブリがロードされたら、ポリシー・マネージャ（Policy Manager）が厳密名の検証処理を開始する。</p><p>　なお厳密名とは簡単にいうと、アセンブリに対して付けられる.NET特有の電子署名のことだ。厳密名はアセンブリに任意で付けることができるが、デフォルトでは付けられない（厳密名の付け方は本稿では割愛する）。厳密名を付けると、ファイルの改ざんをチェックできるので、ファイルを偽装・改ざんするタイプのウイルスを無効化するのに効き目がある。また.NETにはこの厳密名を使用したバージョン管理機能が用意されているので、厳密名を付ければその機能を活用できるというメリットもある。</p><p>　ポリシー・マネージャは、アセンブリのCLRヘッダ（マニフェスト）を解析して、厳密名の有無を確認する。そこで厳密名が設定されていなければ、厳密名の検証処理はスキップする。設定されていれば、厳密名の情報を取得して、それが正当なものかどうかを検証し、偽装・改ざんされたファイルもしくは意図と異なるファイルの実行を防止する。</p><p>　.NETではWindowsの世界に比べてアプリケーション実行時のセキュリティ・チェックが非常に厳重になっているが、ここがCLRの最初のセキュリティ・ポイントだ。</p><p><b>●<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F04.gif" width="16">CLRローダーによる「MainメソッドのILコード上の位置の特定」</b></p><p>　次にCLRローダーは、エントリ・ポイントとなるメソッドのILコード上での位置（＝アドレス）を特定する。具体的には、再度CLRヘッダ（マニフェスト）を解析してエントリ・ポイントのメタデータ・トークン（つまりILコード上のMainメソッドの位置）を取得する。</p><p>　本稿のサンプル・アプリケーションでは、次のようなコードがエントリ・ポイントである。</p><p><code>static void Main()<br>{<br>……中略……<br>} </code></p><p>　このようにC#やVisual Basic .NETでは、基本的にMainメソッドがエントリ・ポイントのメソッドとなる。</p><p><b>●<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F05.gif" width="16">CLRローダーの＜クラス・ローダー＞による「Mainメソッド呼び出しに必要な型情報の収集」</b></p><p>　エントリ・ポイントであるMainメソッドの位置が判明したら、次にクラス・ローダー（Class Loader）がそのMainメソッドを公開している型（例えば本稿では「WindowsApplication1名前空間のForm1クラス」）を取得する。そして、動的に割り当てたメモリ上に、その型の「内部データ構造」（Internal Data Structure）をロードする。</p><p>　クラス・ローダーは、ロードしたクラス情報のメソッド1つ1つに対して、「スタブ」を設定する。スタブとは「ほかのプログラムを呼び出すための仲介となるプログラム」のことだが、ここではそれぞれのメソッドを呼び出すと、（メソッドそのものではなく）メソッドに設定されたスタブを仲介して（次で説明する）「JITコンパイラ」（JIT Compiler。“JITter”ともいう）が呼び出される仕組みになっている。</p><p><b>●<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F06.gif" width="16">CLRローダーによる「Mainメソッドの呼び出し」</b></p><p>　ここでCLRローダーは実際にMainメソッドを呼び出そうとする。そこで先ほどのスタブを仲介して、JITコンパイラが働きだす。具体的には、（次で説明する）「<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F07.gif" width="16">型の妥当性検証」と「<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F08.gif" width="16">変換処理」が実行され、その後の<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F09.gif" width="16">でやっと実際にMainメソッドが実行されることになる。</p><p><b>●<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F07.gif" width="16">CLRローダーの＜JITコンパイラ（型ベリファイア）＞による「型の妥当性検証」</b></p><p>　JITコンパイラが呼び出されると、型ベリファイア（Type Verifier）によって、次の検証処理を実行する。</p><ul><li><p>呼び出そうとしている型やメソッド（のメタデータ情報）が正確・正当なものなのかどうかを調べる</p></li><li><p>呼び出そうとしている型やメソッドのシグネチャが正しいかどうかを調べる</p></li></ul><p>　これらの検証で失敗した場合、例外が発生してプログラムの実行は終了する。これが「タイプ・セーフ」（Type Safe）と呼ばれるセキュリティ・ポイントである。</p><p><b>●<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F08.gif" width="16">CLRローダーの＜JITコンパイラ＞による「ILコードからネイティブ・コードへの変換」</b></p><p>　型の検証処理をパスすると、JIT（Just-In-Time）コンパイラは本来の仕事を開始する。ここがCLRのキモの部分だ。</p><p>　つまりJITコンパイラは、その場で（＝ジャスト・イン・タイムで）、Mainメソッドの「ILコード」を「マシン環境に最適化したCPUネイティブの命令」（基本的には「x86機械語コード」。以降、ネイティブ・コード）にコンパイルして変換する。そして、変換したネイティブ・コードを、動的に割り当てたメモリ・ブロックに格納する（なおこのメモリ上のネイティブ・コードはアプリケーションを終了すると同時に自動的に破棄される）。</p><p>　続いてJITコンパイラは、<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F05.gif" width="16">で用意した型の内部データ構造のMainメソッドのスタブを、ここでコンパイルされたネイティブ・コードのMainメソッドのアドレスに置き換える。これにより、次にMainメソッドを呼び出すときには、（スタブからJITコンパイラが呼ばれるわけではなく）直接にネイティブ・コードを呼び出せる（<font color="#ff0000">※</font>ただしMainメソッドに限っては基本的に2度呼ぶことはないだろうが……）。</p><p>　このように、JITコンパイラによって検証とコンパイルが済んだメソッドは、それが2回以上呼ばれる際にはJITコンパイラを呼ばないようにして、処理を最適化している。</p><p><b>●<img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F09.gif" width="16">CLRローダーの＜コード・マネージャ＞による「ネイティブ・コードの実行と管理」</b></p><p>　Mainメソッドのコードは、CPUが読み取って処理できるネイティブ・コードへと変換されているので、後はそのコードへジャンプすればプログラムが動き始める。これ以降のコード実行は、コード・マネージャ（Code Manager）により管理・制御される。これにより、以下のようなサービスが提供される。</p><ul><li><p>ガーベジ・コレクション（Garbage Collection）：未使用のオブジェクトを自動的に破棄してメモリを解放するサービス</p></li><li><p>例外管理（Exception Manager）：例外処理メカニズムによりアプリケーション・エラーをすべて管理できるサービス</p></li><li><p>セキュリティ（Security Permission Enforcement）：コード・アクセス・セキュリティ（code-access security）によりメソッドなどのコードの実行権限を細かく制御できるサービス</p></li></ul><p><b>●Mainメソッド以降のCLRローダーの処理の流れについて</b></p><p>　Mainメソッド以降の処理の流れでは、メソッドが呼び出されるたびに、その事前処理として、クラス・ローダーによって、メソッド内のすべての型の内部データ構造がメモリ上にロードされ、メソッドにスタブが設定される。当然ながら、すでにメモリ上にロードされている型はロードされない。</p><p>　本稿のサンプル・アプリケーションの例でいえば、MainメソッドでApplicationクラスとForm1クラスの型を使用しているので、 Mainメソッドを呼び出すときにはクラス・ローダーによってこれらの型情報が検出されて、メモリ上にロードされることになる。ただしForm1の型情報は、Mainメソッドをロードするときにすでにロードされているので実際にはここではロードされない。</p><p><code>static void Main()<br>{<br><b>Application</b>.Run(new <b>Form1</b>());<br>} </code></p><p>　なお型情報の検出は、アセンブリの型メタデータを参照して行われる。その型が外部アセンブリのものである場合には、アプリケーション構成ファイル（.configファイル）のコードベース（&lt;codeBase&gt;要素）や、GAC（Global Assembly Cache：グローバル・アセンブリ・キャッシュ）、アプリケーション・パスなどに基づいて外部アセンブリの場所を特定し、上記の「<b><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F02.gif" width="16"></b>アセンブリのロード」「<b><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F03.gif" width="16"></b>厳密名の検証」と同じような処理が実行される。なお、GACのアセンブリを利用する場合は、厳密名の検証処理はスキップされる。</p><p>　型がメモリにロードされたら、実際にメソッドが呼ばれる。この後は<b><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F06.gif" width="16"></b>～<b><img height="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F09.gif" width="16"></b>と同じような処理の流れになる。違うのは、Mainメソッドがほかのメソッドになることである。</p><p align="center">■</p><p>　以上3回にわたり、.NETアプリケーションが動作する仕組みを、コンピュータの世界、Windows（Win32）の世界、.NETの世界という観点から解説した。これで本連載は完結だ。最後までお付き合いいただいたことに感謝の意を表したい。<a href="http://www.atmarkit.co.jp/fdotnet/index.html"><img height="16" alt="End of Article" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2Ficon_end.gif" width="15" border="0"></a> </p>
]]>
</description>
<link>https://ameblo.jp/dokyou/entry-10499373036.html</link>
<pubDate>Sun, 04 Apr 2010 01:41:34 +0900</pubDate>
</item>
<item>
<title>第2回 NETアプリケーションが起動する仕組み</title>
<description>
<![CDATA[ <p>　<a href="http://www.atmarkit.co.jp/fdotnet/dotnetwork/dotnetwork01/dotnetwork01_01.html">前回</a> は、パソコン上でWindows OSやアプリケーション・ソフトウェアなどのプログラムがどのようにして動作しているのかを、PCというハードウェア環境の観点で説明した。今回は、アプリケーションが起動する仕組みについて、Windows OSというソフトウェア実行環境の視点で解説する。</p><p>　ただし、今回説明するのは、.NETアプリケーション（以降、.NETアプリ）が.NET Frameworkの実行環境（「<a href="http://www.atmarkit.co.jp/icd/root/90/14096290.html">CLR：Common Language Runtime</a> 」と呼ばれる）の上で動作を開始するまでの処理過程の話である。実際に.NETアプリケーションがCLRにより実行される仕組みついては次回で解説する予定だ。</p><p>　前置きはこれくらいにして、さっそく「.NETアプリケーションが起動する仕組み（Windowsローダーの働き）」について説明していこう。なお本稿で提示されている図版などは、説明を簡略化するために、すべての詳細を正確に明記してはいないことをあらかじめお断りしておく。</p><h4>Windows OSという視点から見た場合のプログラム実行の仕組み</h4><p>　まずはWindows OSを利用するユーザーの視点で、Windows OS上でアプリケーションが起動する際の処理プロセスについて考えてみよう。</p><p><b>●Windows OS上でアプリケーションが起動する際の処理プロセス</b></p><p>　ここで前提知識として、次のことを知っておいてほしい。</p><p>　それは、.NETアプリケーションであろうと、Win32アプリケーションであろうと、それらのプログラムがWindows OSから最初に起動される処理過程は、基本的に同じであるということだ（なお、「.NETアプリケーション」と「Win32アプリケーション」の違いについては、<a href="http://www.atmarkit.co.jp/fdotnet/dotnetwork/dotnetwork01/dotnetwork01_01.html#proghist">前回</a> の説明を参照してほしい）。</p><p>　従って本稿では、.NETアプリケーションの起動例を取り上げることで、Windows OS上でのアプリケーション起動の仕組みを説明することにした。例に用いる.NETアプリケーションとして、本稿では「WindowsApplication1.exe」というシンプルなWindowsアプリケーションを用意した。</p><p>　次の画面は、そのアプリケーションをダブルクリックして起動したときの、処理の流れを図示したものである。</p><table cellspacing="0" border="0" bgcolor="#e7e3e7" align="center" width="491"><tbody><tr align="center"><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fdotnetwork%2Fdotnetwork02%2Fdotnetwork02_01.gif" style="width: 350px; height: 274px;"></td></tr><tr><td><font size="2"><b>Windows OS上でアプリケーションが起動する際の処理の流れ図</b></font></td></tr><tr><td><font size="2">ディレクトリ（この例では「C:\fdotnet\WindowsApplication1\bin \Release」）の<br>中にあるWindowsアプリケーション「WindowsApplication1.exe」を<br>ダブルクリックして実行したときの処理プロセスを図示したもの。<br>なお、<img height="16" align="absMiddle" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F03.gif">～<img height="16" align="absMiddle" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F04.gif"> の処理プロセスで示されている、CPUおよびメイン・メモリで<br>の処理の流れについては、前回の<br>「<a href="http://www.atmarkit.co.jp/fdotnet/dotnetwork/dotnetwork01/dotnetwork01_02.html#runprogram">Windows 上でプログラムが実行されるまでの処理の流れ</a> 」を併せて<br>参照するとよい。</font></td></tr><tr><td><table cellspacing="0" border="0" width="100%"><tbody><tr><td width="13">&nbsp;</td><td width="10" valign="top"><img height="16" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F01.gif"></td><td><font size="2">ユーザーが「WindowsApplication1.exe」という＜ファイル＞を<br>ダブルクリックする。</font></td></tr><tr><td width="13">&nbsp;</td><td width="10" valign="top"><img height="16" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F02.gif"></td><td><font size="2">Windows OSは、<img height="16" align="absMiddle" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F01.gif">をきっかけとして、クリックされたファイルである「WindowsApplication1.exe」がプログラムかどうかを判定する。</font></td></tr><tr><td width="13">&nbsp;</td><td width="10" valign="top"><img height="16" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F03.gif"></td><td><font size="2">Windows OSは、<img height="16" align="absMiddle" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F02.gif">の作業によりファイルがプログラムと<br>判定されると、そのプログラム・データ（＝プログラム・コード）を<br>メイン・メモリ上にロードしたうえで、＜Win32アプリケーション＞の<br>プログラムとして実行する。</font></td></tr><tr><td width="13">&nbsp;</td><td width="10" valign="top"><img height="16" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F04.gif"></td><td><font size="2">メイン・メモリ上にロードされた「WindowsApplication1.exe」の<br>プログラム・コードを、 CPUが1つずつ処理していく。これにより、<br>.NETの実行環境「CLR」が構築されて、その環境上で<br>アプリケーションが実行される。そして最終的に、 Windows OSの<br>デスクトップ画面上に、［Form1］というタイトルで<br>アプリケーション・ウィンドウが表示される。</font></td></tr></tbody></table></td></tr></tbody></table><p>　それでは、ここで図示されている一連の処理の流れを、1つずつ、もう少し詳しく説明していこう。</p><p><b><a name="exefile"></a>●<img height="16" align="absMiddle" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F01.gif">ユーザーがファイル「WindowsApplication1.exe」をダブルクリックする</b></p><p>　この一連の処理プロセスの中で特に注目すべきは、これまで「プログラム」や「アプリケーション」と呼んでいたものの正体が、実は単なる＜ファイル＞に過ぎなかったということである。なるほど、ファイルの種類には、例えば「テキスト・ファイル」「Word文書ファイル」などなど、いろいろなものがあるが、プログラムもそれらのファイルと本質的には何ら変わらないわけである。</p><p>　しかしよく考えてみると、Windows OSにとってこれが1つの課題・障壁となるのではないだろうか。もしそれらがすべて「ファイル」という同じものであるのならば、Windows OSはそのファイルが一体どのようなものか、つまり「ファイルの種類」（以降、ファイル・タイプ）を認識しなければならないはずだ。このファイル・タイプが分からなければ、そのファイルに対する適切な操作方法（例えば「Windows OS上でプログラムとして直接実行する（Execute）」のか、「アプリケーションでそのファイルを開く（Open）」のかなど）も分からないはずだからである。</p><p>　当然ながらWindows OSはこの課題をクリアしている。例えば、ユーザーが「memo.txt」というテキスト・ファイルをダブルクリックすると、Windows OSは、そのファイルのファイル・タイプを正確に判定して（この例では、「テキスト・ファイルである」と判定される）、ユーザーが要求するアクション（この例では、「アプリケーションでそのファイルを開くこと」）を適切に開始する。これによりWindows OSは、ユーザーが意図するアプリケーションを、正しく起動できるわけである（この例では、「メモ帳（notepad.exe）」などの<a href="http://www.atmarkit.co.jp/icd/root/94/5787394.html">テキスト・エディタ・アプリケーション</a> で実際に開かれる）。</p><p><b>●<font size="2"><img height="16" align="absMiddle" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F02.gif"></font>Windows OSが「WindowsApplication1.exe」がプログラムかどうかを判定する</b></p><p>　このように、OSによるプログラムの起動では、「ファイル・タイプの判定」作業が肝心である。ファイル・タイプの判定方法は、OSごとに異なるが<font color="#ff0000">*1</font>、Windows OSでは、「<a href="http://www.atmarkit.co.jp/icd/root/07/5787207.html">拡張子</a> の名前」（この例では「.exe」）によって行われている（これは「拡張子とファイル・タイプの関連付け」と呼ばれるWindows OSが持つ機能の上に成り立っている）。つまり、先ほどの課題に対するWindows OSの場合の解決方法は、「拡張子」なのである。</p><table cellpadding="5" border="0" bgcolor="#e7e3e7" width="100%"><tbody><tr><td><font size="2" color="#ff0000">*1</font><font size="2"> ちなみにMac OSは、基本的にファイル・タイプを「拡張子」では判定しない。その代わりに、Mac OS専用のファイル・フォーマット（「Mac OS拡張フォーマット」または「HFS Plusフォーマット」と呼ばれる）のヘッダ部分（＝多くの場合、ファイルの先頭部分に配置されるファイル自体の構成内容に関する情報を格納するための領域）にあるファイル情報（「Finder情報」と呼ばれる）を用いて、ファイル・タイプを判別している。ただし最新のMac OS Xなどでは、Windows OSと同じように（Finder情報を使わずに）「拡張子」で判定されるケースも多いらしい。</font></td></tr></tbody></table><p>　Windows OSでは、ファイルの拡張子が「.exe」である場合、そのファイルのファイル・タイプは「<a href="http://www.atmarkit.co.jp/icd/root/11/5785311.html">実行可能ファイル（Executable File）</a> だ」と識別される。つまり、「Windows OS上で実行可能なプログラムである」と判定されるわけだ。</p><p>　従って、本稿の例の「WindowsApplication1.exe」というファイルには、「.exe」という拡張子が付けられているために、実行可能ファイルとして取り扱われて、実際にプログラムとして実行が開始されることになる。</p><p><b>●<img height="16" align="absMiddle" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F03.gif">Windows OSは「WindowsApplication1.exe」をプログラムとして実行する</b></p><p>　プログラムの実行開始を受け持つWindows OSの機能は、「Windowsローダー（Windows Loader）」と呼ばれている。Windowsローダーは、「実行可能ファイル」と判定されたファイルを、「Microsoft Portable Executeフォーマット」<font color="#ff0000">*2</font>（以降、「PEフォーマット」）と呼ばれるプログラム実行用（主にWin32アプリケーション）のファイル・フォーマット（＝ファイル形式）で作成されたファイルとして取り扱う。</p><p>　つまり、すべての実行可能ファイル（.exeファイル）は、PEフォーマットで作成されている必要があるわけだ。これについても、Win32アプリケーションであろうが、.NETアプリケーションであろうが、等しく同じ条件である。すなわち、.NETアプリケーションといえども、Windows OSからは「実行プログラムの1つである」と見えているのだ<font color="#ff0000">*3</font>。</p><table cellpadding="5" border="0" bgcolor="#e7e3e7" width="100%"><tbody><tr><td><font size="2" color="#ff0000">*2</font><font size="2"> PEフォーマットは、Win32アプリケーションの基本フォーマットで、.NETアプリケーションやWin64アプリケーションでも用いられるフォーマットである。</font></td></tr></tbody></table><table cellpadding="5" border="0" bgcolor="#e7e3e7" width="100%"><tbody><tr><td><font size="2" color="#ff0000">*3</font><font size="2"> 厳密にいえば、Windows XPやWindows Server 2003以降のOSは、.NETアプリケーションの存在を知っており、.NETアプリケーションを「Win32アプリケーション」ではなく、きちんと「.NETアプリケーション」として認識している（詳細後述）。</font></td></tr></tbody></table><p>　実行可能ファイルが正しくPEフォーマットで作成されていれば、Windowsローダーは、そのファイルを＜Win32アプリケーション＞のプログラムとして取り扱い始め、実際にプログラムとして起動する。その際の処理過程は次の図のとおりだ。</p><table cellspacing="0" border="0" bgcolor="#e7e3e7" align="center" width="491"><tbody><tr align="center"><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fdotnetwork%2Fdotnetwork02%2Fdotnetwork02_02.gif" style="width: 351px; height: 293px;"></td></tr><tr><td><font size="2"><b>Windowsローダーによるアプリケーションの起動プロセス</b></font></td></tr><tr><td><font size="2">Windowsローダーは、PEフォーマットで作成された実行可能ファイルを、<br>＜Win32アプリケーション＞のプログラムとして起動する。<br>具体的な手順の内容は以下の記述を参照。</font></td></tr></tbody></table><blockquote><p><img height="16" align="absMiddle" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2Fa.gif"> <b>Windowsローダーは、PEフォーマットに基づいて、実行可能ファイルの先頭部分に格納されている情報（以降、「PEヘッダ」）を解析する</b></p><p><img height="16" align="absMiddle" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2Fb.gif"> <b>Windowsローダーは、解析結果に基づき、実行に必要なプログラム・コードをメイン・メモリ上にロードする</b></p><p><img height="16" align="textTop" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2Fc.gif"> <b>Windowsローダーは、解析結果に基づき、プログラムの実行開始位置（Entry Point。以降、「エントリ・ポイント」）にアクセスし、そこに記述された処理命令をCPUに実行させる</b></p><p><img height="16" align="absMiddle" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2Fd.gif"><b> CPUが、そのエントリ・ポイントから順番に1つずつ処理命令を実行していくことで、プログラムが実行開始される</b></p></blockquote><p>　これらの一連のWindowsローダーの処理がすべて完了して、初めてプログラムが現実に実行される（本稿の例でいえば、［Form1］という Windowsアプリケーションのウィンドウが表示される）わけである。</p><p><b>●<font size="2"><img height="16" align="absMiddle" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F04.gif"></font>Windows OSのデスクトップ画面上に、［Form1］というタイトルでアプリケーション・ウィンドウが表示される</b></p><p>　ここまでが、.NETアプリケーションが＜Win32アプリケーション＞として起動するまでの流れである。そして<font size="2"><img height="16" align="absMiddle" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F04.gif"></font>の処理段階からは、.NET Frameworkの実行環境「CLR」へと、その実行の舞台が移される。つまりプログラムが、＜Win32アプリケーション＞という存在から、＜.NETアプリケーション＞という存在へと変ぼうするのだ。この<font size="2"><img height="16" align="absMiddle" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F04.gif"></font>の処理段階以降の話については、次回詳しく説明するので、それまでお待ちいただきたい。</p><p>　以上が理解できたら、<font size="2"><img height="16" align="absMiddle" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F03.gif"></font>の処理内容をもっと具体的に細かく見ていくことにしよう。次のページでは、 Windowsローダーが処理する手順で、プログラムの内部を1つずつ追っていくことにする。</p><br><h4>Windowsローダーがアプリケーションを起動する処理プロセス</h4><p>　それではWindowsローダーの処理を1つずつ順に追っていくことにしよう。</p><p><b>●<img height="16" align="absMiddle" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2Fa.gif">Windowsローダーによる「PEヘッダ」の解析</b></p><p>　Windowsローダーは最初に、PEフォーマットで作成された実行可能ファイルのヘッダ部分、つまり「PEヘッダ」を調べて、どのような起動手順を踏めばよいかを理解する。従ってまずは、このPEヘッダの中身を調べてみよう。</p><p>　私たち人間がPEフォーマットの内容を参照するためのツールとして、「dumpbin.exe」というコマンドライン・ツールがある。本稿ではこれを用いてPEヘッダの内容を解析する。なおdumpbin.exeは、マイクロソフトが提供する統合開発環境のVisual Studio .NETやVisual C++ .NETなどに付属するツールの1つなので、実際に読者諸氏がこのdumpbin.exeを使うには、これらの開発環境のいずれかがコンピュータ上にあらかじめインストールされている必要がある。</p><p>　PEヘッダ情報を確認するには、dumpbin.exeのパラメータ（＝引数）に、実行可能ファイルを指定し（本稿の例では「WindowsApplication1.exe」）、さらに「/header」オプションを付けて実行すればよい。これを、実際に実行しているのが次の画面である。</p><p></p><table cellspacing="0" border="0" bgcolor="#e7e3e7" align="center" width="480"><tbody><tr align="center"><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fdotnetwork%2Fdotnetwork02%2Fdotnetwork02_03.gif" style="width: 350px; height: 255px;"></td></tr><tr><td><font size="2"><b>実行可能ファイル「WindowsApplication1.exe」のPEヘッダの内容</b></font></td></tr><tr><td><font size="2">「WindowsApplication1.exe」という実行可能ファイルのPEヘッダを表示した<br>ところ。 Visual Studio .NET 2003がインストールされた環境で、<br>［スタート］メニューの［すべてのプログラム］－<br>［Microsoft Visual Studio .NET 2003］－［Visual Studio .NET ツール］－<br>［Visual Studio .NET 2003 コマンド プロンプト］を選択すれば、<br>コマンド・プロンプトが表示される。このコマンド・プロンプトには、<br>Visual Studio .NET関連ツールにパスが通っているため、<br>開発関連のツールにフル・パスを指定しなくても、<br>ツール名だけでアクセス（＝利用）できるようになる。</font></td></tr><tr><td><div align="right"><a target="_blank" href="http://www.atmarkit.co.jp/fdotnet/dotnetwork/dotnetwork02/pe_heder.txt"><font size="2">全出力内容を表示する</font></a> </div></td></tr><tr><td><table cellspacing="0" border="0" width="100%"><tbody><tr><td width="13">&nbsp;</td><td width="10" valign="top"><img height="16" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F01.gif"></td><td><font size="2">コマンド・プロンプト内で「cd」コマンドを使って、.NETアプリケーションの<br>あるディレクトリまで移動する。この例では<br>「cd C:\fdotnet\WindowsApplication1\bin\Release」というコマンドを<br>入力して［Enter］キーを押し下げてそのコマンドを実行している。</font></td></tr><tr><td width="13">&nbsp;</td><td width="10" valign="top"><img height="16" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F02.gif"></td><td><font size="2">dumpbin.exeのパラメータに実行可能ファイルを指定して、<br>「/headers」オプションを付けて実行する。この例では、<br>「dumpbin.exe WindowsApplication1.exe /headers」という<br>コマンドを入力して実行している。</font></td></tr><tr><td width="13">&nbsp;</td><td width="10" valign="top"><img height="16" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F03.gif"></td><td><font size="2">コマンド・プロンプト上に出力されたPEヘッダの内容。<br>すべての出力内容は上記の「全出力内容を表示する」のリンクから参照<br>できる。</font></td></tr></tbody></table></td></tr></tbody></table><p></p><p>　上の画面のPEヘッダ情報で表示されている各数値は、基本的に<a href="http://www.atmarkit.co.jp/icd/root/62/5783562.html">16進数</a> <font color="#ff0000">*4</font>で記述されている。なお以降の説明では、16進数の値には、基本的に「0x」というプレフィックス（＝頭文字）を付けて表現する（例えば、「0x400000」）。</p><p></p><table cellpadding="5" border="0" bgcolor="#e7e3e7" width="100%"><tbody><tr><td><font size="2" color="#ff0000">*4</font><font size="2"> 以降の説明を理解するには、16進数を読める必要がある。16進数の数え方を学ぶには、「＠IT自分戦略研究所」の「<a target="_blank" href="http://jibun.atmarkit.co.jp/lskill01/rensai/fe01/fe01.html">コンピュータの基本、2進数を理解しよう</a> 」がお勧めである。</font></td></tr></tbody></table><p></p><p>　次に、このPEヘッダの情報から解析・確認できる次の2点の内容を追いかけてみよう。</p><ol><li><img height="16" align="absMiddle" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2Fb.gif">のメイン・メモリ上にロードされたプログラム・コードの先頭位置（と範囲） </li><li><img height="16" align="textTop" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2Fc.gif"> のエントリ・ポイント（＝実行開始位置）に記述されているプログラム・コード </li></ol><p><b>●<img height="16" align="absMiddle" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2Fb.gif">Windowsローダーによるメイン・メモリ上へのプログラム・データのロード</b></p><p>　まず1の方は、PEヘッダの「OPTIONAL HEADER VALUES」というセクションの「image base」という項目を見れば分かる。本稿の例では、この項目は次のようになっている。</p><p></p><table cellspacing="0" cellpadding="10" border="0" bgcolor="#000066" width="100%"><tbody><tr><td><font color="#ffffff"><code><b>OPTIONAL HEADER VALUES</b><br>　<font color="#ffff00">　…中略……</font><br>　　400000 <b>image base</b> (00400000 to 00407FFF) </code></font></td></tr></tbody></table><p></p><p>　「image base」には、メイン・メモリ上にロードされるときのプログラム・コードの先頭位置のアドレス（＝メモリ上の番地<font color="#ff0000">*5</font>）が示される。従って本稿の例では、メモリ上のアドレス「0x400000番地」を起点として（「0x407FFF番地」のアドレスまでの範囲に）、プログラム・コードがロードされるということが、この「image base」の情報から読み取れる。</p><p></p><table cellpadding="5" border="0" bgcolor="#e7e3e7" width="100%"><tbody><tr><td><font size="2" color="#ff0000">*5</font><font size="2"> ただしこれはプログラマから見えるメモリ空間の「仮想アドレス」で、実際の「物理アドレス」ではない。</font></td></tr></tbody></table>　<br><table cellspacing="0" border="0" bgcolor="#e7e3e7" align="center" width="491"><tbody><tr align="center"><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fdotnetwork%2Fdotnetwork02%2Fdotnetwork02_04.gif" style="width: 349px; height: 217px;"></td></tr><tr><td><font size="2"><b>メイン・メモリ上へのロードされるときのプログラム・コードの先頭位置<br>（とその範囲）</b></font></td></tr></tbody></table><p></p><p><b>●<img height="16" align="textTop" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2Fc.gif">Windowsローダーによるエントリ・ポイントへのアクセス</b></p><p>　次に2の方は、PEヘッダの「OPTIONAL HEADER VALUES」セクションの「entry point」項目に記されている。本稿の例では、次のようになっている。</p><p></p><table cellspacing="0" cellpadding="10" border="0" bgcolor="#000066" width="100%"><tbody><tr><td><font color="#ffffff"><code><b>OPTIONAL HEADER VALUES</b><br>　　<font color="#ffff00">…中略……</font><br>　　3A2E <b>entry point</b> (00403A2E) </code></font></td></tr></tbody></table><p></p><p>　「entry point」項目には、プログラム実行の開始地点（＝プログラム実行のエントリ・ポイント）のメモリ上のアドレスが値として表示される（この例では「0x3A2E」）。ただしこのアドレス値は、先ほどの「image base」のアドレスを基準にした相対的なアドレス値である<font color="#ff0000">*6</font>。従って、本稿の例でいえば、このentry pointの「0x3A2E」という値と、image baseの「0x400000」という値を足し合わせた、「0x403A2E番地」が真のエントリ・ポイントのアドレスということになる。</p><p></p><table cellpadding="5" border="0" bgcolor="#e7e3e7" width="100%"><tbody><tr><td><font size="2" color="#ff0000">*6</font><font size="2"> このような「相対的な仮想アドレス」は、「RVA：Relative Virtual Address」と呼ばれる。</font></td></tr></tbody></table>　<br><table cellspacing="0" border="0" bgcolor="#e7e3e7" align="center" width="491"><tbody><tr align="center"><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fdotnetwork%2Fdotnetwork02%2Fdotnetwork02_05.gif" style="width: 350px; height: 218px;"></td></tr><tr><td><font size="2"><b>プログラム・コードの実行開始地点「エントリ・ポイント」の位置</b></font></td></tr></tbody></table><p></p><p><b>●エントリ・ポイントに記述されているプログラム・コードの内容</b></p><p>　Windows OSは、プログラムを起動開始するために、エントリ・ポイントのアドレス（本稿の例では、「0x403A2E」）に記載されているプログラム・コードを呼び出す。</p><p>　それでは、エントリ・ポイントのアドレスには、一体どのようなプログラム・コードが書かれているのだろうか？ もちろんこれは、実行するアプリケーションによって、さまざまに異なるわけだが、.NETアプリケーションでは、このエントリ・ポイントの部分のプログラム・コードが（基本的に）固定的な内容となっている。実際にはどのような内容になっているのか、そのプログラム・コードの中身を調べてみよう。</p><p>　メモリ上にロードされるときのプログラム・コードの内容を調べるには、先ほども利用したdumpbin.exeに、実行可能ファイルを指定し（本稿の例では「WindowsApplication1.exe」）、さらに「/rawdata」オプションを付けて実行すればよい。これを実際に実行しているのが次の画面である。</p><p></p><table cellspacing="0" border="0" bgcolor="#e7e3e7" align="center" width="491"><tbody><tr align="center"><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fdotnetwork%2Fdotnetwork02%2Fdotnetwork02_06.gif" style="width: 330px; height: 137px;"></td></tr><tr><td><font size="2"><b>「WindowsApplication1.exe」のエントリ・ポイント部分のプログラム・コードの内容</b></font></td></tr><tr><td><font size="2">この例では、「dumpbin.exe WindowsApplication1.exe /rawdata:1,16 | more」<br>というコマンドを入力・実行して、メモリ上にロードされるときの<br>プログラム・コードの内容を参照している（実はこれは、単にファイル内容を<br>ダンプ（＝出力）しているだけで、左端にあるアドレス表示がメモリ上に<br>ロードされるときのアドレスとなっているだけだ。実際のメモリ上の内容を<br>参照しているわけではないので注意すること）。なお、「/rawdata」オプション<br>の後に続く、「:1」は1<a href="http://www.atmarkit.co.jp/icd/root/45/5784945.html">byte</a> （＝8<a href="http://www.atmarkit.co.jp/icd/root/50/5784950.html">bits</a> ）ずつのバイト列を出力するという指定を<br>意味する。これによりexeファイルの内容が16進数2けた（「00」～「FF」）の<br>並びにより表示される。また「,16」は、1行の中に、16進数2けたの値が<br>何個並ぶのかを指定している（この例では、「16」列を指定しているので、<br>「00」「FF」といった数値が16個、横に並ぶことになる）。<br>最後に「 | more」というコマンドが付加されているが、これはページ単位で<br>出力を表示させるためのものである（これを付けないと、全内容が一気に<br>出力されてしまい、目的のアドレス部分を確認できない）。</font></td></tr><tr><td><table cellspacing="0" border="0" width="100%"><tbody><tr><td width="13">&nbsp;</td><td width="10" valign="top"><img height="16" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F01.gif"></td><td><font size="2">「WindowsApplication1.exe」のエントリ・ポイントのアドレスである<br>「0x403A2E」のプログラム・コードを探し出す。</font></td></tr><tr><td width="13">&nbsp;</td><td width="10" valign="top"><img height="16" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F02.gif"></td><td><font size="2">エントリ・ポイント以降にあるプログラム・コードが<br>すべて読み取られる。この例では、「FF 25 00 20 40 00」が<br>読み取れる。なお、どの.NETアプリケーション（.exeファイル）でも<br>この内容は基本的に同じである。ちなみに、.NETで作られた<br>DLL ファイルの場合は、エントリ・ポイントのアドレスも、<br>プログラム・コードの内容も、これとは若干異なる。</font></td></tr></tbody></table></td></tr></tbody></table><p></p><p>　上の画面の内容から、エントリ・ポイント部分のプログラム・コードは、次のような6bytesのコードで成り立っていることが分かる。</p><p></p><table cellspacing="0" cellpadding="10" border="0" bgcolor="#000066" width="100%"><tbody><tr><td><font color="#ffffff"><code>FF 25 00 20 40 00</code></font></td></tr></tbody></table><p></p><p>　このような数値の並び（「<a href="http://www.atmarkit.co.jp/icd/root/75/5784275.html">機械語</a> 」と呼ばれる）を見ただけで、その意味まで読み取ることは難しい（もちろんコンピュータにとっては簡単だが……）。そこで、このようなプログラム・コードを人間が容易に記述したり、読んだりするために、機械語の「数値の並び」が持つ意味（例えば、CPUの処理命令など）に対して「名前」を割り当てた「<a href="http://www.atmarkit.co.jp/icd/root/47/5783847.html">アセンブリ言語</a> 」というものが存在する。</p><p>　ということで、上記の機械語のプログラム・コードを、アセンブリ言語のプログラム・コードへ置き換えてみよう。そうすれば、このプログラム・コードの意味がはっきりするはずだ。</p><p>　まず、先頭の「FF 25」という機械語は、アセンブリ言語の「JMP ＜32bitsアドレス＞」という構文に置き換えられる。この構文に従えば後半に32bitsアドレス（＝4bytes）が続くはずなので、残りの数値である「00 20 40 00」は、そのような4bytesからなる1つのアドレス値に置き換えなければならない。ここで注意が必要である。x86系のCPUアーキテクチャでは、メモリへのデータ格納方法として、「<a href="http://www.atmarkit.co.jp/icd/root/00/49717200.html">リトルエンディアン</a> 」と呼ばれる手法が用いられている。このリトルエンディアン方式では、最下位のバイト（byte）から1つずつ上にさかのぼりながらデータを格納する。つまり、「00 20 40 00」という数値の並びは、最下位のバイトから順に読み取って、「00 40 20 00」→「0x00402000」というアドレスになる。</p><p>　以上の置き換え内容をまとめると、6bytesのコードは次のようなアセンブリ言語の命令文と同等である。</p><p></p><table cellspacing="0" cellpadding="10" border="0" bgcolor="#000066" width="100%"><tbody><tr><td><font color="#ffffff"><code>JMP 0x00402000</code></font></td></tr></tbody></table><p></p><p>　これは「0x00402000番地のアドレスへジャンプ（＝移動）せよ」という処理命令を意味する。よって、ジャンプ先のアドレス「0x00402000」にあるプログラム・コードが次に実行されることになる。</p><p>　それでは、このジャンプ先のアドレスには、どのようなプログラム・コードが存在するのだろうか？ 結論からいうと、ジャンプ先にあるプログラム・コードは、すでに.NETの実行環境の領域に入る。</p><p>　これが意味することは、.NETアプリケーションの起動処理においては、「Win32アプリケーションとして実行されるプログラム・コード（以降、「<a href="http://www.atmarkit.co.jp/icd/root/19/10507419.html">アンマネージ・コード</a> 」）は、たった6bytesしかない」ということだ。それ以外のすべてのプログラム・コードは、.NETアプリケーションとして実行されるプログラム・コード（以降、「<a href="http://www.atmarkit.co.jp/icd/root/18/21224318.html">マネージ・コード</a> 」）である。</p><p>　しかも、Windows XP／Windows Server 2003以降では、Windows OS自体が.NETアプリケーションの存在と起動手順を熟知しているため、いま述べた6bytesのプログラム・コードの実行はスキップして、直接、.NETの領域部分にジャンプして、.NETアプリケーションのプログラム・コードから実行を開始する。つまりこれらのOSでは、完全に.NET環境のみで実行されるのである。</p><p><b>●<img height="16" align="absMiddle" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2Fd.gif">処理命令の順次実行によるプログラムの実行開始</b></p><p>　最後に、先ほど示したジャンプ先のアドレス「0x00402000」に、何があるのかを確かめて今回は終わりにしよう。</p><p>　これを説明する前に、次のことを確認していただきたい。</p><p>　それは、Win32アプリケーションでは、ファイル内のプログラム・コードだけでなく、別ファイルの、具体的には<a href="http://www.atmarkit.co.jp/icd/root/55/5787155.html">DLLファイル</a> （.dll ファイル。ライブラリ）のプログラム・コードも利用することができる、ということだ。</p><p>　このような外部のDLLファイルの使用に関する情報（以降、「インポート情報」）は、あらかじめPEフォーマットのファイル内にデータとして格納されている。</p><p>　そこで、再度コマンドライン・ツール「dumpbin.exe」に登場してもらい、このインポート情報を参照してみよう。これを行うには、 dumpbin.exeのパラメータに.NETアプリケーションを指定し（本稿の例では「WindowsApplication1.exe」）、さらに「/imports」オプションを付けて実行する。これを実際に実行しているのが、次の画面である。</p><p><a name="dotnetentry"></a></p><table cellspacing="0" border="0" bgcolor="#e7e3e7" align="center" width="480"><tbody><tr align="center"><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fdotnetwork%2Fdotnetwork02%2Fdotnetwork02_07.gif" style="width: 349px; height: 254px;"></td></tr><tr><td><font size="2"><b>実行可能ファイル「WindowsApplication1.exe」のインポート情報の内容</b></font></td></tr><tr><td><font size="2">この画面では、「dumpbin.exe WindowsApplication1.exe /imports」という<br>コマンドを入力して、実行可能ファイル「WindowsApplication1.exe」の<br>インポート情報の内容を参照している。なお「/imports」オプションは、<br>実行可能ファイルが使用する（＝インポートする）DLLファイルの一覧情報<br>（＝インポート情報）を表示するためのものである。</font></td></tr><tr><td><div align="right"><a target="_blank" href="http://www.atmarkit.co.jp/fdotnet/dotnetwork/dotnetwork02/pe_imports.txt"><font size="2">全出力内容を表示する</font></a> </div></td></tr><tr><td><table cellspacing="0" border="0" width="100%"><tbody><tr><td width="13">&nbsp;</td><td width="10" valign="top"><img height="16" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F01.gif"></td><td><font size="2">この情報から、「WindowsApplication1.exe」には「mscoree.dll」<br>という外部の DLLファイルを利用している（＝インポートしている）<br>ことが読み取れる。そして、そのインポート情報<br>（Import Address Table）が格納されているメモリ上の<br>先頭アドレスが「0x402000」であることが分かる。</font></td></tr><tr><td width="13">&nbsp;</td><td width="10" valign="top"><img height="16" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F02.gif"></td><td><font size="2">この情報から、「mscoree.dll」のインポート情報のインデックスが<br>「0番」のところに、「_CorExeMain」という関数があるのが分かる。</font></td></tr></tbody></table></td></tr></tbody></table><p></p><p>　この画面を見ると、アドレス「0x00402000」に、「mscoree.dll」というDLLファイルのインポート情報が存在し、さらにそのインポート情報のインデックス「0番」の場所に、「_CorExeMain」という関数が登録されているのが分かる。つまり、先ほどのプログラムのエントリ・ポイントにあったプログラム・コードが実行されると、このインポート情報のアドレス「0x00402000」まで飛んできて、mscoree.dll ファイルにある_CorExeMain関数を呼び出すというわけである（なお、この呼び出し先である_CorExeMain関数のアドレスは、実行時に動的に決定される）。</p><p>　実はこの「mscoree.dll」は、＜.NET Framework＞によりインストールされるDLLファイルの1つで、.NETが動作する環境ならば、Windows OSのシステム・ディレクトリ「<a href="http://www.atmarkit.co.jp/icd/root/04/22710104.html">%Systemroot%</a> \System32」に配置されているはずだ。</p><p>　従って、.NET Frameworkが提供するmscoree.dllの中に含まれる、この_CorExeMain関数こそが、「.NETアプリケーションが.NETとして動作し始める際の最初のエントリ・ポイント」なのである。ちなみに、DLLファイル（.dllファイル）の場合の.NETプログラムとしてのエントリ・ポイントは、mscoree.dllファイルの_CorDllMain関数である（DLLファイルの実行手順については本連載では割愛するが、本稿の手順により調べていけば、それを確かめることができるだろう）。</p><p align="center">■</p><p>　今回はWindows OS上でアプリケーションが起動する仕組みを順を追って解説した。しかし、今回紹介した仕組みは、.NETアプリケーションが.NET Frameworkの実行環境である「CLR」上で動作し始める前の処理段階でしかない。_CorExeMain関数が呼び出された後から、初めて実際に＜.NETアプリケーション＞として動作し始めるわけだが、その仕組みついては次回、解説する。<a href="http://www.atmarkit.co.jp/fdotnet/index.html"><img height="16" border="0" width="15" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2Ficon_end.gif" alt="End of Article"></a> </p>
]]>
</description>
<link>https://ameblo.jp/dokyou/entry-10499371262.html</link>
<pubDate>Sun, 04 Apr 2010 01:37:45 +0900</pubDate>
</item>
<item>
<title>第1回 .NETアプリケーションを動かす土台</title>
<description>
<![CDATA[ <p>　本連載では、新たに.NETで開発を始めようとしている新人プログラマを対象に、.NETアプリケーションが動作する仕組み、つまり「.NETの動作原理」について解説する。</p><p>　もちろん、有能なプログラマや優秀なアーキテクトを目指している読者は、これまでも普通の人よりはコンピュータを使ってきただろう。だから、メール・ソフトやブラウザなどのアプリケーションはある程度思いのままに操れるし、Windows OSのトラブルにも何とか対処できる自信があるに違いない。</p><p>　しかしこれからは、そのような「ソフトウェアがうまく使える能力」を磨くだけでは済まなくなる。これからは、「普通の人に役立つ、面白くて、便利で、使い勝手の良いソフトウェアを開発するための能力」を伸ばしていかなくてはならないはずだ。</p><p>　「そのために、まずは.NET開発を極めたい。それにはプログラムが実行される仕組み、とりわけ.NETの動作原理の基礎はきちんと学んでおきたい。」</p><p>　本連載は、そういう熱意のある新人開発者のための記事である。</p><p>　本連載は、次のような構成で進める予定である。</p><p>第1回 .NETアプリケーションを動かす土台（パソコンとOSの動作原理）<br>第2回 .NETアプリケーションが起動する仕組み（Windowsローダーの働き）<br>第3回 .NETアプリケーションが実行される仕組み（CLRの動作原理）</p><p>　今回は、「パソコンとOSの動作原理」について解説する。それぞれの項目を解説する際には、あまり難しくなりすぎたり、細かくなりすぎたりしないように気を付け、なおかつ基本はきちんと押さえた記事にしていきたい。どうか、連載終了（恐らく3回）までお付き合いいただければ幸いである。</p><h4>Windowsプログラミングの歴史的変化</h4><p><b>●Windows OSの普及と進化</b></p><p>　1995年11月23日。この日、Microsoft Windows 95（日本語版）の発売が開始された。それから今日まで、約10年の歳月が流れたことになる。その間、<a href="http://www.atmarkit.co.jp/icd/root/49/5787249.html">Windows</a>という<a href="http://www.atmarkit.co.jp/icd/root/20/5786020.html">オペレーティング・システム（OS）</a>を利用するコンピューティング環境は、個人、企業、産業を問わずに、急速にかつ幅広く普及した。マイクロソフトは、この10年という年月の流れの中で、Windows OSのバージョンアップを繰り返しながら、機能や<a href="http://www.atmarkit.co.jp/aig/04biz/usability.html">ユーザビリティ</a>（＝使い勝手）、パフォーマンス（＝性能）、セキュリティ（＝安全性）などを大きく向上させてきた。</p><table cellpadding="5" bgcolor="#ffecec" width="100%"><tbody><tr><td><p><b><font size="2" color="#000066">【コラム】Windows OSの歴史</font></b></p><p>　<font size="2">次の表にあるように、これまでマイクロソフトは、新しいバージョンのWindows OSを次々と市場に投入してきた。1995年より以前のバージョンについては、「<a href="http://www.atmarkit.co.jp/icd/root/49/5787249.html">＠IT：Insider's Computer Dictionary [Windows]</a>」を参照してほしい。なお、本表にある「クライアントOS」とは、一般的なユーザーが利用することを目的としたOSを意味し、「サーバOS」とはWebサイト構築やファイル共有などの目的で複数のクライアントからアクセスされることを目的としたOSを意味している。</font></p><table><tbody><tr><td bgcolor="#000066" width="25%"><font size="2" color="#ffffff"><b>OS名</b></font></td><td bgcolor="#000066" width="25%"><font size="2" color="#ffffff"><b>発売日</b></font></td><td bgcolor="#000066"><font size="2" color="#ffffff"><b>説明</b></font></td></tr><tr bgcolor="#ffffff"><td valign="top"><font size="2">Windows 95</font></td><td valign="top"><font size="2">1995年11月23日</font></td><td><font size="2">クライアントOS。MS-DOSなしで利用できる32bit対応OSだが、内部には旧来使われていた16bit カーネルが残されており、システムの安定性に弱いところがある（この系統のOSを、以降では「Windows 9x系」と表記）</font></td></tr><tr><td bgcolor="#e7e3e7" valign="top"><font size="2"><a href="http://www.atmarkit.co.jp/icd/root/87/5787187.html">Windows NT Server 4.0</a></font></td><td bgcolor="#e7e3e7" valign="top"><font size="2"><a href="http://www.microsoft.com/japan/presspass/detail.aspx?newsid=1274" target="_blank">1996年12月10日</a></font></td><td bgcolor="#e7e3e7"><font size="2">サーバOS。完全な32bit対応のOSとして、Windows 9x系とは別に新規開発されたWindows OSで、セキュリティやシステムの安定性に優れている（この系統のOSを、以降では「Windows NT系」と表記）</font></td></tr><tr bgcolor="#ffffff"><td valign="top"><font size="2"><a href="http://www.atmarkit.co.jp/icd/root/87/5787187.html">Windows NT Workstation 4.0</a></font></td><td valign="top"><font size="2"><a href="http://www.microsoft.com/japan/presspass/detail.aspx?newsid=1274" target="_blank">1996年12月10日</a></font></td><td><font size="2">上記Windows NT 4.0のクライアントOS。OSとしての基本機能や信頼性などはサーバ版と共通</font></td></tr><tr><td bgcolor="#e7e3e7" valign="top"><font size="2"><a href="http://www.atmarkit.co.jp/icd/root/36/5784636.html">Windows 98</a></font></td><td bgcolor="#e7e3e7" valign="top"><font size="2"><a href="http://www.microsoft.com/japan/presspass/detail.aspx?newsid=1336" target="_blank">1998年7月25日</a></font></td><td bgcolor="#e7e3e7"><font size="2">Windows 9x系のクライアントOS。Windows 95のメジャー・バージョン・アップ</font></td></tr><tr bgcolor="#ffffff"><td valign="top"><font size="2"><a href="http://www.atmarkit.co.jp/icd/root/81/89606681.html">Windows 98 SE</a></font></td><td valign="top"><font size="2"><a href="http://www.microsoft.com/japan/presspass/detail.aspx?newsid=827" target="_blank">1999年9月10日</a></font></td><td><font size="2">Windows 9x系のクライアントOS。Windows 98のマイナー・バージョン・アップ</font></td></tr><tr><td bgcolor="#e7e3e7" valign="top"><font size="2"><a href="http://www.atmarkit.co.jp/icd/root/54/12480354.html">Windows 2000 Server</a></font></td><td bgcolor="#e7e3e7" valign="top"><font size="2"><a href="http://www.microsoft.com/japan/presspass/releases/112599w2k.htm" target="_blank">2000年2月18日</a></font></td><td bgcolor="#e7e3e7"><font size="2">Windows NT系のサーバOS。Windows NT Server 4.0のメジャー・バージョン・アップ</font></td></tr><tr bgcolor="#ffffff"><td valign="top"><font size="2"><a href="http://www.atmarkit.co.jp/icd/root/54/12480354.html">Windows 2000 Professional</a></font></td><td valign="top"><font size="2"><a href="http://www.microsoft.com/japan/presspass/releases/112599w2k.htm" target="_blank">2000年2月18日</a></font></td><td><font size="2">Windows NT系のクライアントOS。Windows NT Workstation 4.0のメジャー・バージョン・アップ</font></td></tr><tr><td bgcolor="#e7e3e7" valign="top"><font size="2"><a href="http://www.atmarkit.co.jp/icd/root/67/26125567.html">Windows Me</a></font></td><td bgcolor="#e7e3e7" valign="top"><font size="2"><a href="http://www.microsoft.com/japan/presspass/releases/082800winm.htm" target="_blank">2000年9月23日</a></font></td><td bgcolor="#e7e3e7"><font size="2">Windows 9x系最後のクライアントOS。Windows 98のメジャー・バージョン・アップ</font></td></tr><tr bgcolor="#ffffff"><td valign="top"><font size="2"><a href="http://www.atmarkit.co.jp/icd/root/37/100288937.html">Windows XP</a></font></td><td valign="top"><font size="2"><a href="http://www.microsoft.com/japan/presspass/releases/073101.htm" target="_blank">2001年11月16日</a></font></td><td><font size="2">Windows NT系のクライアントOS。Windows 2000 Professionalのメジャー・バージョン・アップ</font></td></tr><tr><td bgcolor="#e7e3e7" valign="top"><font size="2"><a href="http://www.atmarkit.co.jp/icd/root/88/64935988.html">Windows Server 2003</a></font></td><td bgcolor="#e7e3e7" valign="top"><font size="2"><a href="http://www.microsoft.com/japan/presspass/releases03/051503_WS2003.asp" target="_blank">2003年6月25日</a></font></td><td bgcolor="#e7e3e7"><font size="2">Windows NT系のサーバOS。Windows 2000 Serverのメジャー・バージョン・アップ</font></td></tr></tbody></table></td></tr></tbody></table><p>　もちろん進化したのはOSだけではない。そのOS上で動作する個々のアプリケーション・ソフトウェア（以降、アプリケーション）も同様に進化してきた。例えば、インターネット上のWebサイトを参照するための「IE（Internet Explorer）」などは、これまでにもたびたびバージョン・アップしてきたのだ。</p><p><b><a name="proghist"></a>●Windowsにおけるプログラミング環境の変遷</b></p><p>　Windows 95が登場したころのアプリケーションは、Windows OSが提供する<a href="http://www.atmarkit.co.jp/icd/root/57/5787157.html">API</a>（Application Programming Interface：アプリケーションをOS上で動作させるためのインターフェイス。APIは、例えば「ファイルを開く」といった1つの機能をアプリケーションに対して提供するもの）である「Win32 API」を用いて開発することが一般的だった<font color="#ff0000">*1</font>。</p><p>　しかしWin32 APIは、Windows OSと密接に結び付いているため<font color="#ff0000">*2</font>、Windows OSの影響を直接的に受けてしまうという問題があった。Windows OSのバージョン・アップの歴史とは、簡単にいえばWindows OSの機能拡張の歴史でもあるのだが、こうして拡張された機能をアプリケーションが利用できるようにするには、既存のAPIを拡張するか、新しいAPIを追加するしか方法がない。このように増築を繰り返しながら、API全体としての一貫性や統一性を維持することは不可能だ。このためアプリケーション開発者は、OSのバージョンごと（例えば、Windows 98とWindows Server 2003など）でのAPIの違いに注意したり、一貫性のないAPI群を複雑な手順で呼び出したりしなければならず、開発が非常に面倒だったのだ。</p><table cellpadding="5" border="0" bgcolor="#e7e3e7" width="100%"><tbody><tr><td><font size="2" color="#ff0000">*1</font><font size="2"> そのように開発されたアプリケーションは「Win32アプリケーション」と呼ばれる。</font></td></tr><tr><td><font size="2" color="#ff0000">*2</font><font size="2"> Win32APIは、このようなOSの機能に密接に結びついた原始的なシステム・インターフェイスであることから「低水準のAPI」と呼ばれる。逆にインターフェイスを高度に抽象化したもの（例えば、一連の低水準APIの呼び出しを1つのAPIにまとめたものなど）は、「高水準のAPI」と呼ばれる。</font></td></tr></tbody></table><p>　そこで、Windows OSの異なるバージョン間の違い（例えば、Windows 95とWindows XPの違い）をあまり意識する必要がなく、しかもよりシンプルな開発が可能な（つまり、より手軽で簡単にAPIの呼び出しが行える）アプリケーション開発手法が、これまでにいくつも出てきた。</p><p>　例えば、（旧来の）「Visual Basic」というプログラミング・ツールでは、プログラミング初心者がなじみやすいWindowsアプリケーションの画面デザインを中心にした開発が行えるプログラミング手法が提供された。また、「Visual C++」という開発ツールでは、大規模なアプリケーション開発に適した（より効率的な開発が可能となる）「オブジェクト指向」<font color="#ff0000">*3</font>という考え方に基づく「MFC（Microsoft Foundation Class）」というクラス・ライブラリ（＝オブジェクト指向の「クラス」という言語構文機能によって、利用目的ごとにAPIを寄せ集めてまとめたもの。例えば、ファイル操作を目的として「ファイルを開く」「ファイルにデータを書き込む」「ファイルのデータを読み込む」「ファイルを閉じる」という複数の APIを寄せ集めたクラスなど。このようなクラスをたくさん作成してまとめたものがクラス・ライブラリである）が提供されている。</p><table cellpadding="5" border="0" bgcolor="#e7e3e7" width="100%"><tbody><tr><td><font size="2" color="#ff0000">*3</font><font size="2"> オブジェクト指向については「<a href="http://www.atmarkit.co.jp/fdotnet/basics/oop01/oop01_01.html">オブジェクト指向プログラミング超入門</a>」を参照してほしい。</font></td></tr></tbody></table><p>　このようなプログラミング環境の発展のおかげで、Windowsアプリケーションの開発生産性は飛躍的に高まった（つまり、より早く、より多くの機能を簡単に開発できるようになった）。</p><p><b>●現在のWindowsプログラミングの主流「.NET開発」</b></p><p>　そのような開発スタイルの進化は、最終的に「<a href="http://www.atmarkit.co.jp/icd/root/50/50470250.html">.NET Framework</a>」を生み出した。これが現在のWindowsプログラミング手法の主流となっている。</p><p>　.NET Frameworkとは、「現時点で最も高水準かつ高機能なAPI」（＝クラス・ライブラリ）を利用できる開発スタイルだと考えればよい<font color="#ff0000">*4</font>。.NET Frameworkを使えば、高機能なアプリケーションを素早く簡単に開発できるだけでなく、開発できるアプリケーションの種類も、Windowsアプリケーションから、インターネット上のWebサイトとなるWebアプリケーション、<a href="http://www.atmarkit.co.jp/icd/root/72/5784072.html">PDA（Personal Digital Assistants）</a>などの携帯端末までと幅広い<font color="#ff0000">*5</font>。</p><table cellpadding="5" border="0" bgcolor="#e7e3e7" width="100%"><tbody><tr><td><font size="2" color="#ff0000">*4</font><font size="2"> 詳しくは「<a href="http://www.atmarkit.co.jp/fdotnet/basics/msdotnet/msdotnet_01.html">初めてのMicrosoft .NET</a>」を参照してほしい。</font></td></tr><tr><td><font size="2" color="#ff0000">*5</font><font size="2"> .NET Frameworkを用いたアプリケーションの開発方法については、「<a href="http://www.atmarkit.co.jp/fdotnet/easyvs/index/index.html">簡単！Visual Studio .NET入門</a>」や「<a href="http://www.atmarkit.co.jp/fdotnet/basics/oop_index/index.html">オブジェクト指向プログラミング超入門</a>」を参照してほしい。本稿では、そこで開発された.NET Frameworkを用いたアプリケーションが、どのようにして実行されるのかに焦点を当てて解説する。</font></td></tr></tbody></table><p>　本連載では、「このような.NET Frameworkを用いたアプリケーション（以降、.NETアプリケーション）が、どのようにして起動し、どのようにして実行されるのか？」という.NETの仕組み・動作原理について解説していくわけだが、今回は、「そもそも、アプリケーションを動作させる母体であるWindows OSは、どのようにして動いているのか？」ということについて、次のページで解説しよう。</p><br><h4>パソコンの歴史と動作原理</h4><p>　Windows OSは、基本的に、「パソコン」と呼ばれる家電品の上で動作する。パソコンは、いまでは多くの電器店に陳列されて販売されているので、誰でもいつでも手軽に入手して、すぐに使うことができる。しかしパソコンが、現在のように一般消費者の手元に届くようになるまでには、コンピュータの長い進化の歴史がある。コンピュータがパソコンへと発展していった歴史を、ここで簡単に振り返ってみることにしよう。</p><p><b>●コンピュータの発展とパソコンの登場</b></p><p>　1950～1960年ごろの初期のコンピュータは非常に巨大で、それだけでコンピュータ室全体を占拠しまうほどのサイズだった（筆者は実際に見たことはないが、<a href="http://hotwired.goo.ne.jp/news/news/technology/story/20000706304.html" target="_blank">読んだところ</a>によると、最も大きいものでは高さが3メートル、幅が15メートルもあったというのだから、その幅を縦向きにするとビル5～6階建てくらいほどはあるだろうか……）。それほどまでに大きかったため、当然ながら、個人で所有することなどはとても考えられなかった。またその値段も個人ではとても買える水準ではなかった。</p><p>　しかし1970年代に入ると「マイクロ・コンピュータ」（略して、マイコン）と呼ばれる「小型コンピュータ」が作られるようになり、1977年4 月にはアップル社によって開発された「アップルII」という「個人向けコンピュータ」が市場に登場した（Apple社は、現在は<a href="http://www.apple.com/macosx/" target="_blank">Mac OS</a>を提供している）。このとき、アップル社を率いるスティーブ・ジョブズによって初めて使われた名称が「<a href="http://www.atmarkit.co.jp/icd/root/73/139308073.html">パーソナル・コンピュータ</a>」（前出のように「パソコン」とも略される。以降、「PC」と表記）といわれている。その後、IBMが開発したPC（<a href="http://www.atmarkit.co.jp/icd/root/42/5785642.html">IBM PC</a>）が登場し、これと互換性のある「<a href="http://www.atmarkit.co.jp/icd/root/83/5798683.html">PC/AT 互換機</a>」がさまざまなメーカーから発売された。現在“PC”といえば、多くの場合このIBM PCの流れをくむものを指す。</p><p>　PCの性能は時代とともに飛躍的に向上していき、さらには複数のPCをネットワークでつなげて利用することが一般化していった。そして現在の企業システムでは、Windows登場以前では主流だった大型コンピュータ（＝<a href="http://www.atmarkit.co.jp/icd/root/02/5786902.html">メインフレーム</a>）や、メーカー固有の仕様によるコンピュータ（＝<a href="http://www.atmarkit.co.jp/icd/root/50/5786950.html">オフコン</a>）に取って代わり、小型で汎用的な仕様であるPCを使うことが一般的になっている。</p><p></p><table cellspacing="0" border="0" bgcolor="#e7e3e7" align="center" width="480"><tbody><tr align="center"><td><img style="width: 349px; height: 110px;" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fdotnetwork%2Fdotnetwork01%2Fdotnetwork01_01.gif"></td></tr><tr><td><font size="2"><b>巨大なメインフレームから個人で所有できるPCへ</b></font></td></tr></tbody></table><p></p><p><b>●PCの基本的な構成内容</b></p><p>　それではPCは、一体どのようにして動作しているのだろうか。それを知るためには、PCの基本的な構成要素を知っておく必要がある。これについて、次のイラストと表にまとめた。一通りざっと確認してほしい。</p><p></p><table align="center" width="480"><tbody><tr><td colspan="3"><div align="center"><img style="width: 350px; height: 179px;" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fdotnetwork%2Fdotnetwork01%2Fdotnetwork01_02.gif"></div></td></tr><tr><td bgcolor="#000066" width="25%"><b><font size="2" color="#ffffff">ハードウェア名</font></b></td><td bgcolor="#000066" width="25%"><b><font size="2" color="#ffffff">機能名</font></b></td><td bgcolor="#000066" width="50%"><b><font size="2" color="#ffffff">説明</font></b></td></tr><tr><td bgcolor="#e7e3e7" valign="top"><font size="2"><a href="http://www.atmarkit.co.jp/icd/root/44/5785644.html">CPU</a>（中央演算処理装置：Central Processing Unit）</font></td><td bgcolor="#e7e3e7" valign="top"><font size="2">演算・制御装置</font></td><td bgcolor="#e7e3e7"><font size="2">PC上で演算処理を行ったり、<br>ほかのすべての装置を<br>制御したりするための装置。<br>この装置こそがPCのコアと<br>なる頭脳部分である</font></td></tr><tr><td bgcolor="#ffffff" valign="top"><font size="2"><a href="http://www.atmarkit.co.jp/icd/root/78/5785278.html">メイン・メモリ</a></font></td><td bgcolor="#ffffff" valign="top"><font size="2">主記憶装置</font></td><td bgcolor="#ffffff"><font size="2">PC上で何らかの処理作業<br>を行う場合に、一時的な<br>データを記憶するために<br>使用される装置。ここに<br>置かれたデータは電源が<br>切れると消失する。<br>なお、単に「メモリ」と呼ぶ<br>場合、通常はこの<br>「メイン・メモリ」を指す</font></td></tr><tr><td bgcolor="#e7e3e7" valign="top"><font size="2"><a href="http://www.atmarkit.co.jp/icd/root/63/5783863.html">ハード・ディスク</a>、<a href="http://www.atmarkit.co.jp/icd/root/27/5787627.html">CD-ROM</a>／<a href="http://www.atmarkit.co.jp/icd/root/16/5783616.html">DVD-ROM</a>など</font></td><td bgcolor="#e7e3e7" valign="top"><font size="2">補助記憶装置</font></td><td bgcolor="#e7e3e7"><font size="2">PC上で動作する<br>プログラムが使用する<br>記録用データを保存したり、<br>取得したり<br>（＝読み出したり）するため<br>の装置。またWindows OS<br>やプログラム自体の<br>プログラム・データ<br>（＝ソフトウェア）もここに<br>格納される。ここに置かれた<br>データは電源が切れても<br>なくならない</font></td></tr><tr><td bgcolor="#ffffff" valign="top"><font size="2">キーボード、マウスなど</font></td><td bgcolor="#ffffff" valign="top"><font size="2">入力装置</font></td><td bgcolor="#ffffff"><font size="2">コンピュータへの入力を<br>行うための装置。これにより、<br>ユーザーがコンピュータの<br>処理・動作を自由に操作できる</font></td></tr><tr><td bgcolor="#e7e3e7" valign="top"><font size="2">ディスプレイ（画面出力）、プリンタ（印刷）など</font></td><td bgcolor="#e7e3e7" valign="top"><font size="2">出力装置</font></td><td bgcolor="#e7e3e7"><font size="2">コンピュータからの出力を<br>行うための装置。これにより、<br>ユーザーはコンピュータの<br>処理結果を参照したり、<br>活用したりできるようになる</font></td></tr><tr><td valign="top" colspan="3"><img height="5" width="492" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2Ftableline.gif"></td></tr><tr><td bgcolor="#e7e3e7" valign="top" colspan="3"><font size="2"><b>PCの基本的な構成内容</b></font></td></tr><tr><td bgcolor="#e7e3e7" valign="top" colspan="3"><font size="2">本表で示しているのは、PCを動作させるために、最低限必要なPCの<br>構成要素である。なお、これらの装置のように物理的で有形なものは、<br>「<a href="http://www.atmarkit.co.jp/icd/root/25/34726825.html">ハードウェア</a>」と呼ばれる。一方、アプリケーション（プログラム）や<br>データなど目に見えないものは、「<a href="http://www.atmarkit.co.jp/icd/root/35/51601035.html">ソフトウェア</a>」と呼ばれる。</font></td></tr></tbody></table><p></p><p>　以上のPCの構成内容・構造を頭の中に入れたうえで、それをイメージしながら以下の解説を読んでほしい。</p><p><b>●Windows OSが起動するための前提条件</b></p><p>　最初に意識しなければならないのは、次の事実・前提条件である。</p><br><ul><li><b>PCを動かすためのソフトウェア「Windows OS」そのものは、補助記憶装置である「ハード・ディスク」内に格納（＝インストール）されている</b></li></ul><br><p>　この前提条件からスタートして、OSが起動するまでの流れを考えてみよう（なお以下の説明は、厳密な動作内容を表すものではなく、あくまで処理の流れを簡略化して表現したものなので、実際の処理の流れとは完全に一致しない。注意すること）。</p><p><b>●Windows OSが立ち上がるまでの処理の流れ</b></p><p>　PCの電源を入れると、次の流れで処理が進行する。</p><br><blockquote><p><img height="16" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F01.gif"> <b>演算・制御装置である「CPU」が、Windows OSのプログラム・データ（＝ソフトウェア）を、「ハード・ディスク」から取得して、作業用の「メイン・メモリ」の上にロード（＝展開）する</b></p><p><img height="16" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F02.gif"> <b>CPUが「メイン・メモリ」からWindowsのプログラム・データの処理命令を＜フェッチ＞して（＝取り出して）、その命令内容を＜デコード＞（＝解釈）する</b><font color="#ff0000">*6</font></p><p><img height="16" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F03.gif"> <b>CPUがデコードした命令内容を＜実行＞していくことで、プログラム（＝Windows OS）が開始される</b></p></blockquote><br><p></p><table cellspacing="0" border="0" bgcolor="#e7e3e7" align="center" width="480"><tbody><tr align="center"><td><img style="width: 350px; height: 243px;" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fdotnetwork%2Fdotnetwork01%2Fdotnetwork01_03.gif"></td></tr><tr><td><font size="2"><b>PCの電源を入れた後のWindowsが立ち上がるまでの処理の流れ</b></font></td></tr></tbody></table><p></p><p>　この作業が完了すれば、Windows OSが立ち上がることになる。</p><p></p><table cellpadding="5" border="0" bgcolor="#e7e3e7" width="100%"><tbody><tr><td><font size="2" color="#ff0000">*6</font><font size="2"> Windowsのプログラム・データの処理命令はCPUが解釈できる「<a href="http://www.atmarkit.co.jp/icd/root/75/5784275.html">マシン語（機械語）</a>」で記述されている。このマシン語の命令セット（＝処理命令の言語体系）は、CPUのアーキテクチャによって異なる。なお、Windowsで使われている CPUのアーキテクチャは「<a href="http://www.atmarkit.co.jp/icd/root/73/344427273.html">x86</a>」と呼ばれる。</font></td></tr></tbody></table><p></p><p>　この処理の流れは、OSの起動時だけでなく、次に記すようにアプリケーションを実行する場合でも同様だ。</p><p><b><a name="runprogram"></a>●Windows上でプログラムが実行されるまでの処理の流れ</b></p><p>　実際にWindows上でプログラムを実行すると、次のような流れになる。</p><br><blockquote><p><img height="16" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F01.gif"><b> プログラムの実行に必要なプログラム・データを「メイン・メモリ」の上にロードする</b></p><p><img height="16" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F02.gif"> <b>CPUが「メイン・メモリ」からプログラム・データの処理命令を＜フェッチ＞して、その命令内容を＜デコード＞する</b></p><p><img height="16" width="16" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2F03.gif"> <b>CPUがデコードされた命令内容を＜実行＞していくことで、プログラムが開始される</b></p></blockquote><br><p></p><table cellspacing="0" border="0" bgcolor="#e7e3e7" align="center" width="480"><tbody><tr align="center"><td><img style="width: 349px; height: 242px;" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fdotnetwork%2Fdotnetwork01%2Fdotnetwork01_04.gif"></td></tr><tr><td><font size="2"><b>プログラムが立ち上がるまでの処理の流れ</b></font></td></tr></tbody></table><p></p><p>　次回では、このプログラムの実行処理の流れを、Windows OSから実行されるという視点で、より詳しく解説していくつもりだ。</p><p align="center">■</p><p>　以上で今回は終了である。次回は「Windows上でアプリケーションが実行される仕組み」を解説する。これは.NETアプリケーションが.NETで動作し始める前段階の処理過程の説明である。次回は若干難しい話になってくるのである程度覚悟しておいてほしい。<a href="http://www.atmarkit.co.jp/fdotnet/index.html"><img height="16" border="0" width="15" alt="End of Article" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.atmarkit.co.jp%2Ffdotnet%2Fimages%2Ficon_end.gif"></a></p>
]]>
</description>
<link>https://ameblo.jp/dokyou/entry-10499370100.html</link>
<pubDate>Sun, 04 Apr 2010 01:35:31 +0900</pubDate>
</item>
<item>
<title>DirectCompute</title>
<description>
<![CDATA[ <div id="articleHead"><h1>GPGPUをWindowsでサポートする「DirectCompute」</h1><div class="artdata"><p class="date">まずは「GPGPUとはなんぞや？」をおさらいしよう</p></div></div><p>　GPUの高機能化にともない、GPUをグラフィックス処理だけではなく、汎用プログラムを動かしてさまざまな処理をさせようというのが、「GPGPU」(General Purpose GPU)のコンセプトだ。</p><!--  画像が1つで右にキャプションの場合  --><table class="imgphoto" width="498"><tbody><tr><th><a id="eid488275" href="http://ascii.jp/elem/000/000/488/488275/img.html" name="eid488275"><img height="186" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fascii.jp%2Felem%2F000%2F000%2F488%2F488275%2F002_248x.jpg" width="248"></a> </th><td class="rcap" width="245"><p>現在のパソコンは、</p><p>CPUとGPUという</p><p>2つの頭脳を持っている</p><p>(PDC09資料より引用、以下同)</p></td></tr></tbody></table><p>　例えば、GPGPUを利用すればCPUだけで処理するよりも、動画のエンコードやフォーマット変換(トランスコーディング)が高速化できる。 GPGPUに対応しているサイバーリンク(株)の変換ソフト「MediaShow Espresso」では、1920×1080のHDビデオをiPod用のビデオ(解像度640×360ドット)に変換するのに、CPUだけと比べると 40％ほど高速化されるという。もちろん、一概にすべての環境で40％高速化されるわけではないが、低速なCPUでもGPUを利用すれば、高速なトランスコードが可能になる。</p><!--  画像が1つで右にキャプションの場合  --><table class="imgphoto" width="498"><tbody><tr><th><a id="eid488274" href="http://ascii.jp/elem/000/000/488/488274/img.html" name="eid488274"><img height="186" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fascii.jp%2Felem%2F000%2F000%2F488%2F488274%2F001_248x.jpg" width="248"></a> </th><td class="rcap" width="245"><p>現在のGPUは、</p><p>2万円以下の</p><p>グラフィックカードでも</p><p>1TFLOSの性能を有している</p></td></tr></tbody></table><p>　GPGPUはCPUのように、どんなプログラムでも高速に動作するわけではない。GPUのハードウェアを考えれば、物理シミュレーションや金融シミュレーション、ビデオ変換処理など、並列性を生かして単純なデータを一括処理する用途に向いている。</p><!--  画像、キャプションが２つの場合  --><table class="imgphoto" width="500"><tbody><tr><th width="240"><a id="eid488276" href="http://ascii.jp/elem/000/000/488/488276/img.html" name="eid488276"><img height="180" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fascii.jp%2Felem%2F000%2F000%2F488%2F488276%2F004_240x.jpg" width="240"></a> </th><th class="space"><br></th><th width="240"></th></tr><tr><td width="234"><p>DirectComputeを使えば、画像を高速にFFT(フーリエ変換)できる</p><br><p><a id="eid488277" href="http://ascii.jp/elem/000/000/488/488277/img.html" name="eid488277"><img height="180" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fascii.jp%2Felem%2F000%2F000%2F488%2F488277%2F005_240x.jpg" width="240"></a> </p></td><td class="space"><!-- No CDATA --></td><td width="234"><p>GPUによるFFTの</p><p>性能計測結果。 </p><p>DirectComputeで</p><p>GPGPUを使えば、</p><p>CPUだけに比べて2～5倍も速い</p></td></tr></tbody></table><p>　最近のGPGPUの事例としては、長崎大学工学部と独立行政法人理化学研究所が、GPGPUを使ったスーパーコンピューターの開発で、IEEEのゴードン・ベル賞(価格性能比部門)を2009年末に受賞した事例が話題となった。このスーパーコンピューターは380台のGPUを接続して、 158TFLOPSを実現している。天文学や流体力学に使われている「階層化N体シミュレーションプログラム」に特化しているが、「地球シミュレータ」の 122TFLOPSを上回っている。</p><p>　GPGPUは、パソコンのパフォーマンスを大幅に向上すると期待されているが、肝心の対応アプリケーションがなかなか増えてこない。これは、 NVIDIAやAMDなどGPUによって、プログラミング方法が異なるためだ。アプリケーション開発者が両社のGPUに対応しようとすれば、まったく異なるアーキテクチャーを持つNVIDIAとAMD用のプログラムを2つ開発しなければならない。ただでさえ、GPGPUのプログラミングは難しいのに、市場環境を考えれば、両社のGPUに対応するのは大変だ。</p><p>　こうした状況を改善すべく、GPGPU用ソフトウェア開発のための標準化技術が各方面で開発されている。そこにマイクロソフトが提案する技術が「DirectCompute」だ。</p><br><h2>DirectXにDirectComputeを追加</h2><p>　マイクロソフトは、Windowsプラットフォームで使用するグラフィックス機能のAPI群として、DirectXを提供している。 DirectXはDirectX対応GPUと対になって、高速な2D/3Dグラフィックや高品質なテキスト表示(DirectWrite)などを実現しているのはご承知のとおりだ(<a href="http://ascii.jp/elem/000/000/438/438414/">関連記事</a> )。</p><p>　DirectXはグラフィック表示に特化しており、GPUでグラフィック以外のプログラムを動かすためのAPI群は用意されていなかった。そのため、今までNIVDIAやAMDが規定した独自のAPIが使われていたわけだ。しかしDirectComputeは、グラフィック中心のDirectXに統合した形で、GPUにプログラムとデータを送り込む仕組みを実現する。</p><p>　また、DirectComputeのプログラムは、HLSL(High Level Shader Language)というプログラミング言語を利用する。HLSLはC/C++と似たプログラミング言語だ。ただしC/C++と異なるのは、プログラムを中間言語として実行する点にある。NVIDIAやAMDのグラフィックドライバーが、HLSLの中間言語を自社GPU用のコードに変換して実行させる。そのため、GPUメーカーが異なったり世代が異なるGPUでも、同じコードのプログラムをさまざまなGPUで動かせる。</p><!--  画像が1つで右にキャプションの場合  --><table class="imgphoto" width="498"><tbody><tr><th><a id="eid488278" href="http://ascii.jp/elem/000/000/488/488278/img.html" name="eid488278"><img height="186" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fascii.jp%2Felem%2F000%2F000%2F488%2F488278%2F006_248x.jpg" width="248"></a> </th><td class="rcap" width="245"><p>HLSL のコード例。</p><p>プログラミング言語としては、</p><p>C/C++に似ている</p></td></tr></tbody></table><!--  画像が1つで右にキャプションの場合  --><table class="imgphoto" width="498"><tbody><tr><th><a id="eid488279" href="http://ascii.jp/elem/000/000/488/488279/img.html" name="eid488279"><img height="186" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fascii.jp%2Felem%2F000%2F000%2F488%2F488279%2F007_248x.jpg" width="248"></a> </th><td class="rcap" width="245"><p>HLSL のプログラムは</p><p>中間言語</p><p>(Intermediate language)に</p><p>変換され、</p><p>GPUメーカー提供の</p><p>ドライバーで各GPUの</p><p>ネイティブコードに変換される。</p><p>中間言語を使うことで、</p><p>GPUメーカーの違いは</p><p>吸収される</p></td></tr></tbody></table><br><p>当初DirectComputeは、「DirectX 11対応のGPUから対応」と言われていた。しかしマイクロソフトは2008年11月に開催されたハードウェア技術者向け国際会議「WinHEC 2008」で、「DirectX 10.1からサポートする」と表明した。これによりDirectX 10世代のGPUでも、DirectComputeが利用できるようになった。</p><p>　また、DirectComputeはWindows 7だけでなく、Windows Vistaでも利用できるようになった。ただし、VistaでDirectComputeを利用するためには、Windows Updateで提供されている「プラットフォーム更新プログラム」の適用が必要になる(<a href="http://support.microsoft.com/kb/971644/ja" target="_blank">関連リンク</a> )。もちろんDirectComputeに対応したグラフィックドライバーも必要だ。ただ注意が必要なのは、すべてのDirectX 10世代のGPUで、DirectComputeが動作するわけではない(DirectX11世代GPUでは、DirectCompute対応が保証されている)。</p><p><!--  画像、キャプションが２つの場合  --></p><table class="imgphoto" width="500"><tbody><tr><th width="240"><a id="eid488280" href="http://ascii.jp/elem/000/000/488/488280/img.html" name="eid488280"><img height="180" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fascii.jp%2Felem%2F000%2F000%2F488%2F488280%2F009_240x.jpg" width="240"></a> </th><th class="space"><!-- No CDATA --></th><th width="240"></th></tr><tr><td width="234"><p>DirectX 11では、GPUのマルチスレッド化を進化させている。マルチスレッド化により、グラフィック表示とDirectComputeを同時に動かしても問題が起きないようにしている</p><br></td><td class="space"><!-- No CDATA --></td><td width="234"></td></tr></tbody></table><p></p><p><a id="eid488281" href="http://ascii.jp/elem/000/000/488/488281/img.html" name="eid488281"><img height="180" src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fascii.jp%2Felem%2F000%2F000%2F488%2F488281%2F010_240x.jpg" width="240"></a> </p><p>DirectX 11でのパイプラインの流れ<br></p><h2>DirectComputeの普及はCPUとGPUの統合が進む2011年からか？</h2><p>　本稿執筆時点では、市販されているDirectX 11世代のGPUは、AMDのRadeon HD 5000シリーズしかない。しかし2010年には、NVIDIAからもDirectX 11世代GPUが登場するだろうから、普及もそれなりに進み、DirectComputeを使ったアプリケーションが徐々にリリースされると期待される。</p><p>　DirectComputeは最初のうち、ビデオのエンコード/トランスコードなど、ビデオ関連のアプリケーションで使われるだろう。その後は Adobe PhotoshopやIllustratorなど、現在はGPUメーカー固有のAPIを使っている写真編集/グラフィックソフトでも使われるとみられる。</p><p>　グラフィック分野以外の用途では、アンチウィルスソフトのカスペルスキー・ラボ社が、GPGPU技術でウィルススキャンを高速化するアイデアも検討しているという。またゲームなどでは、NPC(コンピューター操作のキャラクター)の行動を、GPGPUで計算するようになるかもしれない。同種の技術はすでに、プレイステーション3用ゲームで活用されている。</p><p>　さらに2011年には、AMDがCPUにGPUを統合した「APU」(Accelerated Processing Unit)、コード名「Llano」をリリースする(<a href="http://ascii.jp/elem/000/000/484/484074/index-3.html">関連記事</a> )。またインテルでも、計画は仕切り直しになったが「Larrabee」のようなデータ並列ユニットを、CPUに取り込むことを考えている。Windows 7登場で一気にDirectComputeが普及する……とはいかないかもしれないが、2年後にCPUがGPGPUの機能を取り込むようになれば、より多くの対応アプリケーションが登場することだろう。</p>
]]>
</description>
<link>https://ameblo.jp/dokyou/entry-10498768763.html</link>
<pubDate>Sat, 03 Apr 2010 13:25:42 +0900</pubDate>
</item>
<item>
<title>Microsoft DirectX</title>
<description>
<![CDATA[ <p><b>Microsoft DirectX</b>（ダイレクトエックス）は、<a title="マイクロソフト" href="http://ja.wikipedia.org/wiki/%E3%83%9E%E3%82%A4%E3%82%AF%E3%83%AD%E3%82%BD%E3%83%95%E3%83%88">マイクロソフト</a>社が開発した<a title="ゲーム" href="http://ja.wikipedia.org/wiki/%E3%82%B2%E3%83%BC%E3%83%A0">ゲーム</a>および<a title="マルチメディア" href="http://ja.wikipedia.org/wiki/%E3%83%9E%E3%83%AB%E3%83%81%E3%83%A1%E3%83%87%E3%82%A3%E3%82%A2">マルチメディア</a>処理用の<a title="Application Programming Interface" href="http://ja.wikipedia.org/wiki/Application_Programming_Interface">API</a>の集合である。</p><p>DirectXコンポーネントのうち、グラフィックスを担うDirectX Graphicsは<a title="Microsoft Windows" href="http://ja.wikipedia.org/wiki/Microsoft_Windows">Microsoft Windows</a>、<a title="Xbox" href="http://ja.wikipedia.org/wiki/Xbox">Xbox</a>、<a title="Xbox 360" href="http://ja.wikipedia.org/wiki/Xbox_360">Xbox 360</a>向けの<a title="パソコンゲーム" href="http://ja.wikipedia.org/wiki/%E3%83%91%E3%82%BD%E3%82%B3%E3%83%B3%E3%82%B2%E3%83%BC%E3%83%A0">ゲーム</a>開発で広く利用されている。DirectX互換の<a title="ビデオカード" href="http://ja.wikipedia.org/wiki/%E3%83%93%E3%83%87%E3%82%AA%E3%82%AB%E3%83%BC%E3%83%89">ビデオカード</a>を利用することにより、高品質の3Dグラフィックスを高速に<a title="レンダリング (コンピュータ)" href="http://ja.wikipedia.org/wiki/%E3%83%AC%E3%83%B3%E3%83%80%E3%83%AA%E3%83%B3%E3%82%B0_%28%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%29">レンダリング</a>できるため、DirectXはこれ以外のソフトウェア産業、特にエンジニアリングの分野でも広く利用されている。</p><p>DirectXの<a title="ランタイムライブラリ" href="http://ja.wikipedia.org/wiki/%E3%83%A9%E3%83%B3%E3%82%BF%E3%82%A4%E3%83%A0%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA">ランタイムライブラリ</a>と<a title="ソフトウェア開発キット" href="http://ja.wikipedia.org/wiki/%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E9%96%8B%E7%99%BA%E3%82%AD%E3%83%83%E3%83%88">SDK</a>は、いずれもマイクロソフトの<a title="ウェブサイト" href="http://ja.wikipedia.org/wiki/%E3%82%A6%E3%82%A7%E3%83%96%E3%82%B5%E3%82%A4%E3%83%88">ウェブサイト</a>から無償でダウンロードできるが、<a title="プロプライエタリ・ソフトウェア" href="http://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%83%97%E3%83%A9%E3%82%A4%E3%82%A8%E3%82%BF%E3%83%AA%E3%83%BB%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2">プロプライエタリ</a>で<a title="ソースコード" href="http://ja.wikipedia.org/wiki/%E3%82%BD%E3%83%BC%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%89">ソースコード</a>は非公開である。DirectXはWindowsに含まれているが、最新版をウェブサイトからダウンロードすることが可能である。</p><p><a title="2009年" href="http://ja.wikipedia.org/wiki/2009%E5%B9%B4">2009 年</a>11月現在の最新バージョンは、DirectX 11.0である。これは、<a title="Microsoft Windows 7" href="http://ja.wikipedia.org/wiki/Microsoft_Windows_7">Windows 7</a>に同梱されており、<a title="Microsoft Windows Vista" href="http://ja.wikipedia.org/wiki/Microsoft_Windows_Vista">Windows Vista</a>においてはWindows Updateを通じて入手可能である。(DirectX 10以降は、Windowsのグラフィックアーキテクチャに大規模な修正が加えられた事と、<a title="Windows Display Driver Model" href="http://ja.wikipedia.org/wiki/Windows_Display_Driver_Model">Windows Display Driver Model</a>が導入された事から、<a title="Microsoft Windows XP" href="http://ja.wikipedia.org/wiki/Microsoft_Windows_XP">Windows XP</a>などの旧Windows製品では利用できない。)</p>
]]>
</description>
<link>https://ameblo.jp/dokyou/entry-10498767179.html</link>
<pubDate>Sat, 03 Apr 2010 13:24:23 +0900</pubDate>
</item>
<item>
<title>FLOPSとGHz</title>
<description>
<![CDATA[ <span class="answer" id="14861154">Hzは元々振幅を表す単位でヘルツ（周波数単位）といいます。例えば、電気のコンセントの交流電流は50Hz/60Hzで一秒間に電流が正負に50回または60回振幅しています。これは、ゆとり教育でどうなったか分かりませんが、小学校～中学校の理科で習う項目です。オシロスコープなどを使うかな？<br><br>パソコンでいう動作周波数（正確にはクロック周波数と言います）は、この振幅を1秒間に何回するかを表した物です。それが性能にどのように直結するかというと、これは電気の流れだと思えば分かりやすいのです。<br>周波数の山や谷のどちらかまたは両方のエッジ（波頂点か谷の頂点）、一定量のデータをサーフィンで波にのっているかのように載せるのです。<br>波が小刻みであればその波にのって大量のデータが一秒間に運ばれます。<br><br>例えば、1GHzで1Hz辺り64bit（8バイト）のデータを転送できる64bitバスのプロセッサなら、2GHzで16GBの情報を1秒間で扱うことができます。実際には周波数は最大値ですか、波に乗り遅れたり、データが乗った波をうまく計算部で演算できず破棄される（遭難する）ケースもありますけどね。<br><br>即ち、まったく同じ構造のCPUなら性能の指標になります。（違う構造だとロスの数やバス幅が異なる場合がありますから、性能指標になりません）<br>ただ、どれだけ転送できるかであり、どれだけの計算が出来ているかではないので、他のプロセッサと比べられないのです。<br><br>flopsはFloating point number Operations Per Secondの略で、1秒間（Per Second)に浮動小数点演算（Floating Point nunber/FP）をどれだけできるか（Operating/操作や制御の意訳）を指します。<br>flopsが１であれば、1秒間に1回。10なら10回です。1000回なら1Kflops（キロフロップス）、100万回なら１Mflops（メガフロップス）、10億回なら1Gflops（ギガフロップス）となり、1兆回なら1Tflops（テラフロップス）、1000兆回なら、1Pfops（ペタフロップス）となります。<br><br>これは、FPU（浮動小数点演算装置）の性能を測るためのもので、既に枯れつつあるALU（整数演算装置）の性能指標ではないことに注意してください。同じFPUでもインテルCPUの場合は、SIMDを利用するため、32bit単精度と64bit倍精度で数値が2倍（または1/2）に変化します。<br>単精度であれば、2コアがフル稼働すると仮定した場合に、3GHzでCore2は倍精度24Gflopsを達成できます。（クロックの4倍×2コア）<br>単精度なら、その1/2になります。<br>Core2はスカラ型の演算ユニットを利用する特性上、実際の実行クロックはそれより低くなります。<br><br>尚、これらの演算性能はOSやミドルウェア、アプリケーションなどの土俵が最適化されていての話です。例えば、Cellを使うPS3が200Gflops を扱えるCPUでも、実際のソフトでそれを活用できるものの開発には時間が掛かりました。そのため、数字上の理論値や実行値と本当に業務に有用なソフトを使う上での性能は必ずしも比例するとは限りません。まあ、x86に関しては、同じプロセッサの延長線上にあるので、新しいほど高速化しますけどね。</span>
]]>
</description>
<link>https://ameblo.jp/dokyou/entry-10498761195.html</link>
<pubDate>Sat, 03 Apr 2010 13:14:10 +0900</pubDate>
</item>
<item>
<title>解像度と階調</title>
<description>
<![CDATA[ <font face="Courier New"><h3>解像度</h3><p>ビットマップ方式ではピクセルと呼ばれる小さな領域の集まりと考え、ピクセルごとの色を記録する。</p><p>ピクセルはドットと呼ばれたり画素(画素)と呼ばれたりする。</p><p>当然ピクセルが多いほど正確に細かく記録することができるが、その分データが多く必要になる。この違いを<strong>解像度</strong>という。細かい部分をどれだけ詳しく分解できるかという意味である。</p><p></p><table><tbody><tr><td>ピクセル数</td><td>208×160=33280</td><td>104×80=8320</td></tr><tr><td>画像</td><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.seiai.ed.jp%2Fsys%2Ftext%2Fcs%2Fchp02%2Fimg%2Fsmpl01.png"></td><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.seiai.ed.jp%2Fsys%2Ftext%2Fcs%2Fchp02%2Fimg%2Fsmpl02.png"></td></tr><tr><td>ピクセル数</td><td>52×40=2080</td><td>26×20=520</td></tr><tr><td>画像</td><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.seiai.ed.jp%2Fsys%2Ftext%2Fcs%2Fchp02%2Fimg%2Fsmpl04.png"></td><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.seiai.ed.jp%2Fsys%2Ftext%2Fcs%2Fchp02%2Fimg%2Fsmpl08.png"></td></tr></tbody></table><p></p><p>上図は写真を撮る時を想定して像をピクセルに分け、ピクセルの色を１色に決定することを表しているので、26×20=520 の解像度のピクセルは大きい。しかし、記録されたデータのピクセルをどのぐらいの大きさにするかは表示の時の都合による。</p><p>ピクセル大きさを同じにした画像</p><p></p><table><tbody><tr><td>ピクセル数</td><td>208×160=33280</td><td>104×80=8320</td></tr><tr><td>画像</td><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.seiai.ed.jp%2Fsys%2Ftext%2Fcs%2Fchp02%2Fimg%2Fsmpl01.png"></td><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.seiai.ed.jp%2Fsys%2Ftext%2Fcs%2Fchp02%2Fimg%2Fsmpl02s.png"></td></tr><tr><td>ピクセル数</td><td>52×40=2080</td><td>26×20=520</td></tr><tr><td>画像</td><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.seiai.ed.jp%2Fsys%2Ftext%2Fcs%2Fchp02%2Fimg%2Fsmpl04s.png"></td><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.seiai.ed.jp%2Fsys%2Ftext%2Fcs%2Fchp02%2Fimg%2Fsmpl08s.png"></td></tr></tbody></table><p></p><p>解像度は、１インチ（25.4mm）あたりのピクセル数で表され、dpi（dots per inch）、ppi (pixels per inch)という単位を使う。</p><p>コンピュータ画面の解像度はピクセル数をそのままいうことが多い。1024x768、1280x1024、1600x1200 などが代表的である。</p><p>これをdpiに直すには次のように計算する。画面の横幅が 30cm で 1024 ピクセルである場合、1024÷(30÷2.54)＝86.7…なので約87dpiとなる。普通のディスプレイは72dpi～96dpi程度の解像度で表示している。</p><p>印刷などで、各色の色の点が隣り合い、集まって一つの色の単位をなす場合、各色の点をドット、集まって一つの色の単位をピクセルというが、インクが混ざって一つの点をなす時にはドットとピクセルは一致する。</p><h3>階調</h3><p>ピクセルごとにどんな色かを記録していくが、その色をどこまで細かく区別していくかを<strong>階調</strong>という。普通は赤緑青の三原色それぞれ２５６段階の組み合わせで２５６×２５６×２５６＝１６７７７２１６色で表したものをフルカラーとか２４bitカラーなどと呼ぶ。</p><p>以下の例は、青のグラデーションを２５６段階から８段階まで、何段階に区別するかを変化させてどのように記録されるかをみたものである。</p><p>左側の列をみると解像度が高くても（細かくサンプリング）段階の数が十分にないと再現性が悪くなることがわかる。</p><p>また、右側は左側の８分の１の解像度で同様に階調を減らしていったものである。解像度と階調の意味することの違いを確認してほしい。</p><p></p><table><tbody><tr><th id="bslash">ピクセル数→<br>階調↓</th><th>200×150=30000</th><th>25×19=475</th></tr><tr><th>256</th><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.seiai.ed.jp%2Fsys%2Ftext%2Fcs%2Fchp02%2Fimg%2Fqnt256.png"></td><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.seiai.ed.jp%2Fsys%2Ftext%2Fcs%2Fchp02%2Fimg%2Fqnt256s.png"></td></tr><tr><th>64</th><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.seiai.ed.jp%2Fsys%2Ftext%2Fcs%2Fchp02%2Fimg%2Fqnt064.png"></td><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.seiai.ed.jp%2Fsys%2Ftext%2Fcs%2Fchp02%2Fimg%2Fqnt064s.png"></td></tr><tr><th>32</th><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.seiai.ed.jp%2Fsys%2Ftext%2Fcs%2Fchp02%2Fimg%2Fqnt032.png"></td><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.seiai.ed.jp%2Fsys%2Ftext%2Fcs%2Fchp02%2Fimg%2Fqnt032s.png"></td></tr><tr><th>16</th><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.seiai.ed.jp%2Fsys%2Ftext%2Fcs%2Fchp02%2Fimg%2Fqnt016.png"></td><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.seiai.ed.jp%2Fsys%2Ftext%2Fcs%2Fchp02%2Fimg%2Fqnt016s.png"></td></tr><tr><th>8</th><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.seiai.ed.jp%2Fsys%2Ftext%2Fcs%2Fchp02%2Fimg%2Fqnt008.png"></td><td><img src="https://img-proxy.blog-video.jp/images?url=http%3A%2F%2Fwww.seiai.ed.jp%2Fsys%2Ftext%2Fcs%2Fchp02%2Fimg%2Fqnt008s.png"></td></tr></tbody></table><p></p></font>
]]>
</description>
<link>https://ameblo.jp/dokyou/entry-10498760036.html</link>
<pubDate>Sat, 03 Apr 2010 13:11:19 +0900</pubDate>
</item>
</channel>
</rss>
