問題#
- 情報の 2 つの要素。
ビット + コンテキスト。 - テキストファイルは何で構成されていますか?
ASCII 標準表の文字。 - ソースプログラムからターゲットプログラムへの 4 つの段階は?
前処理、コンパイル、アセンブル、リンク。 - システムハードウェアの 4 つの部分は?
プロセッサ、主記憶、I/O デバイス、バス。 - 論理的に見た主記憶はどのようなものですか?
一連の線形バイト配列で、各バイトには一意のアドレスがあります。 - 主記憶ハードウェアは何で構成されていますか?
動的ランダムアクセスメモリ(DRAM)。 - プロセッサのコアは何ですか?主に何をしますか?
プログラムカウンタ、次の命令のアドレスを保存します。 - プロセッサの動作プロセスを最も簡単な方法で説明してください。
PC が指し示す命令を実行し、その後 PC を更新します。 - 命令操作はどの 3 つの部品の周りで実行されますか?
主記憶、レジスタ、ALU(算術論理ユニット)。レジスタは命令、データ、状態などを保存し、ALU は計算を行います。 - 4 つの命令操作:ロード、ストア、操作、ジャンプはそれぞれ何ですか?
(1) ロード(Load):これはメモリからデータをレジスタまたは他のプロセッサ内部にロードする操作です。
(2) ストア(Store):これはレジスタまたは他のプロセッサ内部からメモリにデータを保存する操作です。
(3) 操作(Arithmetic/Logical):これはプロセッサ内部で算術または論理演算を実行する操作を含みます。算術操作には加算、減算、乗算、除算などが含まれます;論理操作にはビット操作(AND、OR、NOT、XOR など)が含まれます。
(4) ジャンプ(Jump):これはプログラムの実行順序を変更するための操作です。 - 命令セットアーキテクチャとマイクロアーキテクチャはそれぞれ何ですか?
命令の効果を記述します。ハードウェアの実装方法です。 - CPU がターゲットファイルを実行するプロセスは?
ファイルをディスクに保存し、レジスタに読み込み、次に主記憶に置きます(直接アクセスによりレジスタを経由せずに実現できます)、ターゲットファイルの命令を実行します。 - ソースプログラムから実行結果を得るまでの全プロセスは?
ソースプログラム -> ターゲットプログラム -> プロセッサがターゲットプログラムを実行 - 主記憶はディスクよりどれくらい速いですか?レジスタはディスクよりどれくらい速いですか?
千万倍、百倍。 - L1 キャッシュはどこにありますか?どのくらいの大きさですか?どのくらいの速さですか?L2 は?
CPU 上にあり、数十 MB で、L2 より 5 倍速い;L2 は特別なバスを介して CPU に接続され、数百 MB から数 GB で、主記憶より 5〜10 倍速いです。 - キャッシュはどのように使用されますか?
頻繁にアクセスされるデータを保存します。 - メモリ階層構造は何層ありますか?主な考え方は何ですか?
7 層で、上の層を次の層のキャッシュとして使用します。 - オペレーティングシステムの 3 つの基本的な抽象概念は何ですか?
ファイル、仮想メモリ、プロセス。 - プロセスとは何ですか?プロセスの特徴は何ですか?
システムが実行中のプログラムであり、システムはある時点で 1 つのプロセスしか実行できません。 - オペレーティングシステムカーネルとは何ですか?主に何をしますか?
オペレーティングシステムの主記憶に常駐する部分で、プロセスの切り替えを管理します。方法はコンテキストスイッチです。 - 仮想アドレス空間とは何ですか?いくつの部分で構成されていますか?
プロセスが見るのは仮想のアドレス空間です。低い方からプログラムコードとデータ、ランタイムヒープ、共有ライブラリ、ユーザースタック、カーネル仮想メモリが続きます。 - 同時実行と並列実行の違い、順次実行の違いは何ですか?
同時実行は交互に実行され、並列実行は同時に行われ、順次実行は 1 つが完了してから次を実行します。 - スレッドレベルの並列とは何ですか?
4 つのコアで 1 つのコアが 1 つのスレッドを持つ場合、4 スレッドの並列です。 - スーパースレッディングとは何ですか?
スーパースレッディングは 1 つのコアで 2 つのスレッドを実現できます。PC やレジスタなどのハードウェアには複数のバックアップがあり、1 つのスレッドがコピーを待っているときに別のスレッドを実行できます。これはハードウェアを十分に活用して異なるスレッドを交互に実行することに相当します。 - 命令レベルの並列とは何ですか?
1 つの命令には 20 以上のクロックサイクルが必要で、並列化することで 1 秒間に 2〜4 の命令を実行できます。 - 単一命令・多データ並列とは何ですか?
1 つの命令のいくつかの単純な操作を並行して実行します(ハードウェアレベル)。 - 命令セットアーキテクチャとは何ですか?
抽象的なもので、命令が順次実行されるように見えますが、実際には背後で命令レベルの並列が行われています。
1.1 情報はビット + コンテキストです#
プログラム#
- プログラムのライフサイクルは ** ソースプログラム(ソースファイル)** から始まります。ソースプログラムは実際には 0 と 1 から構成されるビット列です。
- 一般的にはASCII 標準を使用してテキスト文字を表現し、実際には 1 バイトの整数値を使用して 1 つの文字を表現します。
- ソースファイルの各テキスト行は、見えない '\n' で終了します。
- ASCII 文字のみで構成されるファイルはテキストファイルと呼ばれ、その他はバイナリファイルです。例えば.cpp ファイルはテキストファイルです。
- システム内のすべての情報は一連のビット(bit:ビット)で表されており、異なるデータオブジェクトを区別する唯一の方法はコンテキストに基づくことです。
C 言語の特徴#
- C 言語は小さくシンプルです。
- C 言語は Unix を実現するために設計されました。
- C 言語は Unix と密接に関連しています。
C 言語はシステムレベルのプログラミングの第一選択であり、アプリケーションレベルのプログラムにも非常に適しています。
1.2 プログラムは他のプログラムによって異なる形式に翻訳されます#
#include <stdio.h>
int main(){
printf("こんにちは、世界!\n");
return 0;
}
ソースプログラムからターゲットプログラムへの4 つのステップ:#
- ソースプログラムは前処理器によって処理され、修正されたソースプログラム(テキストファイル、hello.i)が得られます。
- 次にコンパイラによって処理され、アセンブリプログラム(テキストファイル、hello.s)が得られます。
- アセンブリプログラムはアセンブラによって処理され、再配置可能なターゲットプログラム(バイナリファイル、hello.o)が得られます。
- 最後にリンカによってリンクされ、実行可能なターゲットプログラム(バイナリファイル、hello)が得られます。
- 前処理段階:前処理器(cpp)は、# で始まるコマンドに基づいて元の C プログラムを修正します。例えば、
hello.c
の最初の行の#include <stdio.h>
コマンドは、前処理器にstdio.h
の内容を読み込み、プログラムテキストに直接挿入するよう指示します。最終的に別の C プログラムが得られ、通常は.i
がファイル拡張子として使用されます。 - コンパイル段階:コンパイラ(ccl)はテキストファイル
hello.i
をテキストファイルhello.s
に翻訳し、アセンブリ言語プログラムを含みます。このプログラムにはmain
関数の定義が含まれています。
1 main:
2 subq $8, %rsp
3 movl $.LC0, %edi
4 call puts
5 movl $0, %eax
6 addq $8, %rsp
7 ret
- アセンブリ段階:次に、アセンブラ(as)は
hello.s
を機械語命令に翻訳し、これらの命令を再配置可能なターゲットプログラム(relocatable object program)という形式にパッケージ化し、結果をターゲットファイルhello.o
に保存します。hello.o
ファイルはバイナリファイルであり、17 バイトはmain
関数の命令コードを含んでいます。 - リンク段階:注意すべきは、
hello
プログラムがprintf
関数を呼び出していることです。これはすべての C コンパイラが提供する標準 C ライブラリの関数です。printf
関数はprintf.o
という名前の別の事前コンパイルされたターゲットファイルに存在します。リンカ(ld)はこのファイルを私たちのhello.o
ファイルに統合し、最終的にメモリにロードされ、システムによって実行される実行可能ターゲットファイルhello
を得ます。
1.3 コンパイルシステムの理解は非常に役立ちます#
役立つ点#
- プログラムのパフォーマンスを最適化する
- リンク時に発生するエラーを理解する
- セキュリティホールを避ける
1.4 プロセッサはメモリに保存された命令を読み取り解釈します#
シェルはコマンドラインインタプリタであり、プロンプト(>>)を出力し、コマンドラインの入力を待ち、命令を実行します。入力が実行可能ファイルの名前であれば、そのファイルを実行します。
1.4.1 システムのハードウェア構成#
主にバス、I/O デバイス、プロセッサ、主記憶の 4 つの部分を含みます。
バス#
- バスは一度に一定長のバイトブロックを転送します。これをワードと呼びます。64 ビットシステムでは、バスは一度に 64 ビット(8 バイト)を転送します。ここで 1 ワードは 8 バイトです。
I/O デバイス#
- 各 I/O デバイスはコントローラまたはアダプタを介して I/O バスに接続されています。
- コントローラは I/O デバイス自体またはマザーボード上のチップセットであり、アダプタはマザーボードに挿入されたカードです。
主記憶#
- 主記憶は一組の ** 動的ランダムアクセスメモリ(DRAM)** で構成されています。
- 論理的に見て、メモリは線形のバイト配列であり、各バイトには一意のアドレスがあります。
プロセッサ#
- プロセッサは主記憶に保存された命令を解釈するエンジンです。
- プロセッサのコアは ** プログラムカウンタ(PC)** です。
- プログラムカウンタは1 ワードのサイズのストレージデバイスで、CPU が次に実行する命令のアドレスを保存します。
- プロセッサは常にプログラムカウンタが指し示す命令を実行しています。各命令を実行するたびに、プログラムカウンタは更新され、次の命令を指し示します。
- プロセッサは** 命令実行モデル(命令セットアーキテクチャ)** に従って、命令内のビットを解釈し、対応する操作を実行します。
- 各命令の操作は主記憶、レジスタファイル、算術論理ユニット(ALU)の周りで行われます。
レジスタファイル#
- 単一ワード長で、一意の名前があります。
ALU#
- 簡単な命令の操作:
- ロード:主記憶から 1 ワードまたはバイトをレジスタにコピーし、元の内容を上書きします。
- ストア:レジスタから 1 ワードまたはバイトを主記憶にコピーし、元の内容を上書きします。
- 操作:2 つのレジスタの内容を ALU にコピーし、ALU がこれらの 2 つのワードに対して算術演算を行い、結果を 1 つのレジスタに保存します。
- ジャンプ:命令から 1 ワードを抽出してプログラムカウンタにコピーし、元の内容を上書きします。
プロセッサの命令セットアーキテクチャとマイクロアーキテクチャの違い:
- 命令セットアーキテクチャ:各機械命令の効果。
- マイクロアーキテクチャ:プロセッサが実際にどのように実装されているか。
1.4.2 hello プログラムの実行#
- ターゲットファイルを実行する際、シェルプログラムはディスク上のターゲットファイルの文字を 1 つずつレジスタに読み込み、次に主記憶に保存します。その後プロセッサはターゲットファイルの機械語命令を実行し、
main
プログラムから開始します。** 直接メモリアクセス(DMA)** を利用することで、レジスタを経由せずにディスクからメモリにデータを直接読み込むことができます。 - 全プロセス:ファイルの文字をレジスタに読み込む -> 主記憶に保存する -> 命令を実行する ->
hello world
をレジスタにロードする -> ディスプレイにコピーする -> 表示する
1.5 キャッシュは非常に重要です#
- 主記憶から 1 ワードを読み取るのはディスクよりも 1000 万倍速いです。
- レジスタファイルから読み取るのは主記憶よりも 100 倍速いです。
- キャッシュ(cache)はプロセッサと主記憶の間の差異を解決するために使用されます。
- L1 キャッシュは CPU 上にあり、容量は数万バイト(数十 MB)です。L1 は L2 より 5 倍速いです。
- L2 キャッシュは特別なバスを介して CPU に接続され、容量は数十万から数百万バイト(数百 MB から数 GB)です。L2 は主記憶よりも5〜10倍速いです。
- キャッシュに頻繁にアクセスされる可能性のあるデータを保存することで、大部分のメモリ操作がキャッシュ内で完了します。
1.6 ストレージデバイスは階層構造を形成します#
- メモリ構造は合計 7 層で、主な考え方は上の層のメモリを下の層のキャッシュとして使用することです。
- 上から下に行くほど、容量が大きく、動作が遅く、1 バイトあたりの価格が安くなります。
- 0 層:レジスタ
- 1 層:L1 キャッシュ(SRAM)
- 2 層:L2 キャッシュ(SRAM)
- 3 層:L3 キャッシュ(SRAM)
- 4 層:主記憶(DRAM)
- 5 層:ローカルセカンダリストレージ(ローカルディスク)
- 6 層:リモートセカンダリストレージ(分散ファイルシステム、Web サーバー)
1.7 オペレーティングシステムはハードウェアを管理します#
- オペレーティングシステムの2 つの基本機能:
- ハードウェアが制御不能なアプリケーションによって乱用されるのを防ぎます。
- アプリケーションに複雑な低レベルのハードウェアデバイスを制御するためのシンプルで一貫したメカニズムを提供します。
- オペレーティングシステムが適用する3 つの基本的な抽象概念:
- プロセス:プロセッサ、主記憶、I/O デバイスの抽象表現。
- 仮想メモリ:メモリとディスクの抽象表現。
- ファイル:I/O デバイスの抽象表現。
1.7.1 プロセス#
- プロセス:オペレーティングシステムが実行中のプログラムの抽象です。
- 並行実行:1 つのプロセスの命令と別のプロセスの命令が交互に実行されます。1 つのシステムは同時に複数のプロセスを実行できますが、実際にはこれらのプロセスは並行して実行されています。
- オペレーティングシステムはコンテキストスイッチを通じて並行実行を実現します。コンテキストはプロセスの実行に必要なすべての状態情報を追跡するもので、PC、レジスタファイル、主記憶などに存在する可能性があります。
- 任意の時点で、単一のプロセッサは 1 つのプロセスのコードしか実行できません。
- オペレーティングシステムのカーネルはオペレーティングシステムコードが常駐するメモリの部分であり、1 つのプロセスから別のプロセスへの切り替えはカーネルによって管理されます。
- カーネルは独立したプロセスではなく、一連のコードとデータ構造の集合です。
- アプリケーションがオペレーティングシステムの特定の操作を必要とする場合、制御権をカーネルに渡します。カーネルは操作を完了した後、アプリケーションに戻ります。
1.7.2 スレッド#
- 1 つのプロセスは複数のスレッドで構成されています。各スレッドはプロセスのコンテキスト内で実行され、同じコードとグローバルデータを共有します。
- マルチスレッド間でのデータ共有はマルチプロセス間でのデータ共有よりも容易であり、一般的にスレッドはプロセスよりも効率的です。
1.7.3 仮想メモリ#
- マシンプログラムはメモリを巨大なバイト配列として見なし、これを仮想メモリと呼びます。
- メモリの各バイトはアドレスによって識別され、すべての可能なアドレスの集合が仮想アドレス空間です。
- 仮想メモリにより、各プロセスは主記憶を独占していると考えます。各プロセスが見るメモリは一貫性があり、すなわち仮想アドレス空間です。
- Linux では、各プロセスが見る仮想アドレス空間は以下の部分で構成されています:
- プログラムコードとデータ
- ヒープ(ランタイムヒープ)
- 共有ライブラリ
- スタック(ユーザースタック)
- カーネル仮想メモリ
- アドレスは低い方から高い方へ、最上層のカーネル仮想メモリにはオペレーティングシステム内のコードとデータが保存されており、この部分はすべてのプロセスで同じです。
- プログラムコードとデータ:すべてのプロセスにとって、コードは同じ固定アドレスから始まり、その後にグローバル変数に対応するデータ領域が続きます。コードとデータ領域は実行可能ファイルの内容に基づいて初期化されます。コードとデータ領域はプロセスが実行を開始する際にサイズが指定されます。
- ヒープ:ランタイムヒープは
malloc
とfree
関数の呼び出しに基づいて実行時に動的に拡張および縮小されます。 - 共有ライブラリ:アドレス空間の中間部分は共有ライブラリのコードとデータを保存するために使用されます。C 標準ライブラリ、数学ライブラリなどが共有ライブラリに該当します。
- スタック:ユーザースタックはヒープと同様に、プログラム実行中に動的に拡張および縮小されます。コンパイラはこれを関数呼び出しを実現するために使用します。関数を呼び出すとスタックが増加し、関数から戻るとスタックが縮小します。
1.7.4 ファイル#
- ファイルはバイト列です、それだけです。
- 各 I/O デバイス、ディスク、キーボード、ディスプレイ、ネットワークを含めて、すべてがネットワークとして見なすことができます。
1.8 システム間でネットワーク通信を利用します#
- 単独のシステムから見ると、ネットワークは I/O デバイスとして見なすことができます。
- 例えば、遠隔サーバーでプログラムを実行する場合、ローカルで入力し、遠隔で実行し、実行結果をローカルに送信して出力します。
1.9 主要なテーマ#
1.9.1 Amdahl の法則#
- Amdahl の法則の主な見解:全システムを加速するには、全システムの中で相対的に大きな部分を改善する必要があります。
1.9.2 同時実行と並列実行#
- 同時実行と並列実行の違い:
- 同時実行:複数の活動を持つシステムを指す一般的な概念です。
- 並列実行:同時実行を利用してシステムをより速く動作させることです。
- 並列実行は複数の抽象レベルで適用できます。高いレベルから低いレベルには以下の 3 つのレベルがあります:
- スレッドレベルの並列
- 伝統的な意味での並行実行は、単一プロセッサがプロセス間で迅速に切り替えることでシミュレートされます。
- マルチプロセッサシステムは、1 つのオペレーティングシステムが複数の CPU を制御します。構造は以下の通りです。
- L1 キャッシュは 2 つの部分に分かれています:最近取得した命令を保存する部分とデータを保存する部分です。
- スーパースレッディングは同時マルチスレッディングとも呼ばれ、1 つの CPU が複数の制御フローを実行できるようにします。 CPU のハードウェアには、プログラムカウンタやレジスタファイルなどの複数のバックアップがあり、他のハードウェアは 1 つだけです。例えば浮動小数点算術演算ユニットです。通常の CPU はスレッドを切り替えるのに約20000クロックサイクルを必要としますが、スーパースレッディング CPU は単一のサイクルの基礎の上でスレッドを切り替えることができます。例えば、1 つのスレッドがデータをキャッシュにロードするのを待っているとき、CPU は別のスレッドを実行できます。
- i7 プロセッサは各コアで 2 つのスレッドを実行するため、4 コア 8 スレッドで、8 つのスレッドが並行して実行されます。
- 命令レベルの並列
- 各命令は開始から終了まで一般的に 20 クロックサイクル以上を必要とします。命令レベルの並列化により、各サイクルで 2〜4 の命令を実行する速度を実現できます。
- 1 サイクルあたり 1 命令よりも速い場合は、スーパースカラプロセッサと呼ばれ、現在は一般的にスーパースカラです。
- 単一命令・多データ並列
- 最も低いレベルでは、現代のプロセッサは1 つの命令が複数の並行して実行可能な操作を生成することを許可します。これを単一命令・多データ並列、すなわち SIMD 並列と呼びます。
1.9.3 コンピュータシステムにおける抽象の重要性#
- 命令セットアーキテクチャは CPU ハードウェアの抽象です。CPU は実際には機械コードプログラムの 1 つの命令を実行しているように見えますが、実際には底層ハードウェアが並行して複数の命令を実行しています。
- 仮想マシンはオペレーティングシステム、プロセッサ、プログラムを含むコンピュータシステム全体の抽象です。