| プログラム実行 |
|---|
| 一般的な概念 |
| コードの種類 |
| コンパイル戦略 |
| 注目すべき実行時間 |
| 注目すべきコンパイラとツールチェーン |
|
コンピューティングにおいて、実行とは、コンピュータプログラムがエンコードされたアクションを実行するために処理されるプロセスです。プロセッサがプログラム命令に従うと、命令の意味に従って効果が生成されます。「実行」という用語は一般的に同義です。実行を開始する行為は、「実行」や「実行中」に加えて、「起動」や「呼び出し」と呼ばれることもあります。
実行プロセッサには様々な形態があります。マシンコードプログラムは、コンピュータのプログラマブルインターフェースを介して実行され、制御ユニットによって実行される各プログラム命令について、フェッチ、デコード、実行サイクルを繰り返し実行します。ソースコードは、インタープリタソフトウェアによって実行されます。プログラムは、人間の介入なしにバッチプロセスで実行される場合もあれば、ユーザーが対話型セッションでコマンドを入力する場合もあります。
実行の側面はソフトウェア開発に影響を与え、推進します。
多くの場合、ソフトウェアは、実行可能ファイルをコンピューターとその周辺機器の直接操作から切り離すサービスを提供し、プラットフォームに依存しないソリューションを提供するために、ホスト環境に合わせたランタイム環境やランタイム ライブラリなどの外部サービスに依存します。
実行時エラーはプログラムの実行後または実行中(実行状態)に検出されますが、コンパイル時エラーはプログラムの実行前にコンパイラによって検出されます。型チェック、レジスタ割り当て、コード生成、およびコード最適化は通常コンパイル時に行われますが、言語やコンパイラによっては実行時に行われる場合もあります。その他多くの実行時エラーが存在し、プログラミング言語によって処理方法が異なります。たとえば、ゼロ除算エラー、ドメインエラー、配列添字の範囲外エラー、算術アンダーフローエラー、数種類のアンダーフローおよびオーバーフローエラー、および一般にソフトウェアのバグと見なされるその他の多くの実行時エラーは、特定のコンピュータ言語では検出および処理されない場合があります。
例外処理は実行時エラーの処理をサポートし、予期しない状況だけでなく、予測可能なエラーや異常な結果も構造的に捕捉する方法を提供します。例外処理のない言語で必要とされるインラインエラーチェックは必要ありません。近年のランタイムエンジンの進歩により、自動化された例外処理が可能になり、対象となるすべての例外の「根本原因」デバッグ情報を提供します。これは、ランタイムエンジンに特別なソフトウェア製品をアタッチすることで、ソースコードとは独立して実装されます。
一部のデバッグは実行時にのみ実行可能です(あるいは実行時に実行した方が効率的または正確です)。例えば、論理エラーや配列境界チェックなどが挙げられます。そのため、高度なコンパイル時チェックやリリース前テストを実施しても、一部のプログラミングバグは、実際のデータを用いて本番環境でテストするまで発見されません。このような場合、エンドユーザーは「実行時エラー」メッセージに遭遇する可能性があります。
実行環境とは、プログラムが実行されるコンテキストです。以下の注目すべき環境属性は一般的に使用されます。環境は複数の属性で記述される場合もあるため、厳密に区別されるわけではありません。
ホストネイティブは、特に歴史的に見て、一般的な実行シナリオです。これは、中央処理装置(CPU)の命令を介してコンピューターを制御することを意味します。CPUはプログラムを機械語レベルで解釈します。
コンテキストスイッチングは、マルチタスクオペレーティングシステム(OS)の機能であり、複数のホストネイティブ実行ファイルの同時実行をサポートします。実行ファイル(プロセスコンテキスト識別子で識別される)を実行環境からスワップアウトするために、OSはメモリページアドレスやレジスタ値などの実行コンテキストデータを保存します。スワップインするために、OSはこれらのデータを復元します。[ 1 ] : 3.3 [ 2 ]
LinuxベースのOSでは、レジスタに格納されたデータセットは通常、コンテキストスイッチを実装するためにメモリ内のプロセス記述子に保存されます。[ 1 ] PCIDも使用されます。
プログラムが起動されると、ローダーがメモリのセットアップを行い、プログラムに必要な動的リンクライブラリとリンクします。その後、プログラムのエントリポイントから実行が開始されます。言語や実装によっては、これらのタスクを言語ランタイムが代わりに実行する場合もありますが、これは一般的なコンシューマー向けオペレーティングシステム上の主流言語では珍しいケースです。
ランタイムシステムは、実行ファイルにサービスを提供するソフトウェア層です。これは実行モデルの一部です。関連して、ランタイム環境(RTE)は、ランタイムシステムを含む、プログラムが対話できるすべてのものを指します。
ほとんどのプログラミング言語にはランタイムシステムが含まれています。ランタイムシステムは、メモリ管理、変数アクセス、パラメータ渡しの仕組み、オペレーティングシステムへのアクセスなど、様々な問題に対応します。コンパイラは、特定のランタイムシステムに応じて仮定を立て、コードを生成します。通常、ランタイムシステムはスタックとヒープの設定と管理に一定の責任を負い、ガベージコレクション、スレッド、その他の言語の動的機能などを含む場合があります。 [ 3 ]
命令サイクルとは、CPUが起動からシャットダウンまで命令を処理するために実行する サイクルです。命令サイクルは、フェッチステージ、デコードステージ、実行ステージという3つの主要なステージで構成されます。

より単純なCPUでは、命令サイクルは順次実行され、各命令が処理されてから次の命令が開始されます。一方、現代のCPUのほとんどでは、命令サイクルは命令パイプラインを介して同時実行され、多くの場合並列実行されます。つまり、サイクルが複数のステップに分割されているため、前の命令が完了する前に次の命令の処理が開始されます。[ 4 ]
仮想マシン(VM)は、ホストシステムに直接アクセスする代わりに、ソフトウェア層として部分的または完全に実装された物理コンピュータの機能を提供します。仮想化により、VMは比較的薄いソフトウェア層を介してホストコンピュータおよびホスト上の他のVMから論理的に独立したコンピュータシステムを提供します。これにより、ホストのテクノロジによる制約を受けるという代償を払う代わりに、比較的高いパフォーマンスが可能になります。エミュレーションにより、VMはホストコンピュータシステムのテクノロジとは大きく異なる可能性のある独自のコンピュータを提供しますが、一般的に、比較的厚いソフトウェア層のためにパフォーマンスが比較的低速になります。
VMテクノロジーは、その適用範囲によって異なります。システムVM(完全仮想化VMとも呼ばれます)は、独立したオペレーティングシステムを実行するために必要な機能を提供します。ハイパーバイザーは、ネイティブ実行を使用してハードウェアを共有および管理することで、同一の物理マシン上に複数の独立した環境を共存させることができます。最新のハイパーバイザーは、主にホストCPUから提供される、仮想化に特化したハードウェアであるハードウェア支援型仮想化を使用します。一方、プロセスVM( .NET、Java、Pythonランタイムなど)は、プラットフォームに依存しない環境でコンピュータプログラムを実行します。
QEMUやビデオゲームコンソールエミュレータなどの一部のエミュレータは、異なるシステムアーキテクチャをエミュレート(または「仮想的に模倣」)するように設計されており、これにより、別のCPUまたはアーキテクチャ向けに作成されたソフトウェアアプリケーションやオペレーティングシステムの実行が可能になります。OSレベルの仮想化により、コンピュータのリソースをカーネルを介して分割できます。これらの用語は、必ずしも互換性があるわけではありません。
インタプリタは、直接実行可能な形式のコードを実行します。環境に必要な準備作業はすべて既に実行されています。実行ファイルはCPU(仮想CPUを含む)で直接実行できます。ソースコードは、それをサポートする環境で実行できます。例えば、JavaScriptやPythonは、コンパイル操作を必要としないインタプリタソフトウェアによって実行されます。