この章では、helloプログラムのライフサイクルを追跡することにより、コンピューターシステムの学習を開始します。ソースプログラムは、プログラマーによって作成されたときに開始され、システム上で実行され、簡単なメッセージを出力してから終了します。このプログラムのライフサイクルに沿って徐々に出現しているいくつかの重要な概念、技術用語、およびコンポーネントを簡単に紹介します。
記事ディレクトリ
私は長い間ブログを更新していません。国民の日から現在まで、秋の募集、再開テンプレート、埋め込まれたソフトウェアインタビューの知識ポイントの要約、秋の募集の筆記試験の質問の並べ替え、および対面の概要レビューに関する情報を整理してきました。合計400ページ近くの16Wワードが整理されました。ちなみに、Baidu Netdiskの情報も整理しましたが、10.16まで完成しませんでした(情報が必要な場合はホームページに連絡先があります)。情報の整理は本当に人間だと言わざるを得ません。
次の計画は、オペレーティングシステムとコンピューター構成の原則に関連する知識を補足することです。「コンピュータシステムの詳細な理解」という本から始めて、CMUのビデオシステムで「コンピュータシステムの詳細な理解」という本を学びましょう。理解を深めるために使用できるラボは9つあります。当初の計画では、週に1つの章を作成し(それが機能するかどうかはわかりません)、冬休みの前にこれを完了するように努めます。
本を読む過程でいくつかの重要な知識のポイント、概念の理解と実験を行うための詳細な過程をブログで、コンピュータシステムのコラムの深い理解に置きます。私のブログをフォローして、記事の更新されたコンテンツをできるだけ早く入手することを歓迎します。
以下は、この本の最初の章の簡単な要約です。
ソースプログラムはどのように保存されますか
#include <stdio.h>
int main()
{
printf("hello,world\n");
return 0;
}
上記のプログラムは、テキストエディタで作成され、hello.cとして保存されたテキストファイルです。ソースプログラムは、実際には値0と1で構成されるビットのシーケンス(ビットとも呼ばれます)です。8ビットは、バイトと呼ばれるグループに編成されます。各バイトは、プログラム内のテキスト文字を表します。最近のコンピューターは、ASCII標準を使用してテキスト文字を表します。hello.cプログラムのASCIIテキスト文字を以下に示します。
hello.cプログラムは、バイトのシーケンスとしてファイルに保存されます。
hello.cの表現方法は、基本的な考え方を示しています。ディスクファイル、メモリ内のプログラム、メモリに保存されているユーザーデータ、ネットワーク上で送信されるデータなど、システム内のすべての情報はビット文字列で表されます。異なるデータオブジェクトを区別する唯一の方法は、これらのデータオブジェクトのコンテキストを読み取るときです。
ソースプログラムから実行可能ファイルへのプロセス
GCCコンパイラドライバは、ソースファイルhello.cを読み取り、それを実行可能オブジェクトファイルhelloに変換します。この変換プロセスは、事前コンパイル、コンパイル、アセンブリ、およびリンクの4つの段階に分けることができます。
プリコンパイル済み
コンパイル前のプロセスでは、主にソースコード内の命令の前処理、ヘッダーファイルの導入、コメントの削除、すべての条件付きコンパイル命令(#ifdef、#ifndef、#else、#elif、#endif)の処理、およびマクロの置換を処理します。 、行番号を追加し、すべてのコンパイラ命令を保持します。
コンパイル
前処理が終了すると、コンパイルされます。コンパイルプロセスは、前処理されたファイルに対して文法分析、字句分析、意味分析、シンボルの要約を実行してから、アセンブリコードを生成します。
コンパイル
アセンブリプロセスは、アセンブリコードをバイナリファイルに変換し、バイナリファイルをマシンで読み取ることができます。各アセンブリステートメントは、機械言語の文を生成します。
リンク
アセンブラによって生成されたオブジェクトファイルはすぐには実行できず、未解決の問題が多数ある可能性があります。たとえば、ソースファイル内の関数は、別のソースファイルで定義されたシンボル(変数や関数呼び出しなど)を参照する場合があります。ライブラリファイル内の関数は、プログラムで呼び出される場合があります。これらの問題はすべて、リンクプログラムの処理によってのみ解決できます。リンカーの主な役割は、関連するオブジェクトファイルを相互に接続することです。つまり、あるファイルで参照されているシンボルを別のファイルのシンボルの定義に接続して、これらすべてのオブジェクトファイルがオペレーティングシステムでインストールできるものになるようにします。実行の統一された全体に。
シェルは何ですか
シェルはコマンドラインインタープリターであり、プロンプトを出力し、コマンドラインが入力されるのを待ってからコマンドを実行します。コマンドラインの最初の単語が組み込みのシェルコマンドでない場合、シェルはこれが実行可能ファイルの名前であると想定し、ファイルをロードして実行します。
典型的なシステムのハードウェア構成
バス
システム全体を実行しているのは、バスと呼ばれる一連の電子チャネルです。通常、固定長のバイトブロックはバス、つまりワードで送信されます。ワードのバイト数(ワード長)は、基本的なシステムパラメータです。システムが異なれば、語長も異なります。たとえば、32ビットシステムのワード長は4バイトで、64ビットシステムのワード長は8バイトです。
IOデバイス
I / O(入力/出力)機器は、システムと外界との間の通信チャネルです。この例のシステムには、4つのI / Oデバイスが含まれています。ユーザー入力用のキーボードとマウス、ユーザー出力用のモニター、およびデータとプログラムを長期間保存するためのディスクドライブ(つまり、ディスク)です。
各IOデバイスは、コントローラーまたはアダプターを介してI / Oバスに接続されます。コントローラとアダプタの主な違いは、パッケージにあります。コントローラは、I / Oデバイス自体のチップセット、またはシステムのメインプリント回路ボード(通常はマザーボードと呼ばれます)です。アダプターは、マザーボードのスロットに挿入されるカードです。いずれにせよ、それらの機能は、I / OバスとI / Oデバイス間で情報を転送することです。
メインメモリ
メインメモリは、プロセッサがプログラムを実行するときにプログラムとプログラムによって処理されるデータを格納するために使用される一時的なストレージデバイスです。物理的に言えば、メインメモリは動的ランダムアクセスメモリ(DRAM)チップのグループで構成されています。論理的に言えば、メモリは線形バイト配列であり、各バイトには一意のアドレス(配列インデックス)があり、これらのアドレスはゼロから始まります。
プロセッサ
プロセッサと呼ばれる中央処理ユニット(CPU)は、メインメモリに格納されている命令を実行するエンジンです。プロセッサのコアは、プログラムカウンタ(PC)と呼ばれる1ワードのサイズのストレージデバイス(またはレジスタ)です。PCはいつでも、メインメモリ内の特定の機械言語命令(つまり、命令を含むアドレス)を指します。
helloプログラムを実行します
シェルがキーボードから入力した「./hello」を読み取った後、コンピューター内の情報フローは次の図の赤い線で示されます。
キーボード-> USBコントローラー-> I / Oバス-> I / Oブリッジ->システムバス->登録
レジスタ->システムバス-> I / Oブリッジ->メモリバス->メインメモリ
シェルプログラムは、ユーザーの入力を変数として使用する必要があります。この変数は、最終的にメモリに到達するように、メモリ内にアドレスを持っている必要があります。
キーボードのEnterキーを押すと、シェルプログラムはコマンド入力が完了したことを認識します。次に、シェルは一連の命令を実行して実行可能なhelloファイルをロードします。これらの命令は、helloターゲットファイル内のコードとデータをディスクからメインメモリにコピーします。データには、最終的に出力される文字列「hello、wor1d \ n」が含まれています。情報の流れは以下のとおりです。
ディスク->ディスクコントローラ-> I / Oバス-> I / Oブリッジ->メモリバス->メインメモリ
データにアクセスするこの方法は、CPUを通過せず、ディスクからメインメモリに直接通過します。この方法はDMAと呼ばれます。DMA(ダイレクトメモリアクセス)は、CPUの負荷を軽減し、データの転送中にCPUが他のタスクを実行できるようにします。
helloファイルをロードした後、CPUはhelloプログラムのメイン関数から命令の実行を開始します。これらの命令は、文字列「hello、world \ n」のバイトをメインメモリからレジスタファイルにコピーし、次にレジスタファイルから表示デバイスにコピーして、最後に画面に表示します。情報の流れを下図に示します。
メインメモリ->レジスタ->システムバス-> I / Oブリッジ-> I / Oバス->グラフィックアダプタ->ディスプレイ
キャッシュ
helloプログラムを実行することで、レジスタ、メインメモリ、ディスク間で命令とデータを何度もコピーする必要があることがわかります。これらのコピーは実際にはオーバーヘッドであり、プログラムの速度が低下します。今回は、この問題を解決するためにメモリをキャッシュする(キャッシュメモリ)必要があります。
L1キャッシュの容量は数万バイトに達する可能性があり、アクセス速度はレジスタファイルとほぼ同じです。
特別なバスを介してプロセッサに結合された、数十万から数百万バイトの L2キャッシュ容量。プロセスがL2キャッシュにアクセスする時間は、L1キャッシュにアクセスする時間の5倍ですが、それでもメインメモリにアクセスする時間の5〜10倍高速です。
L1およびL2キャッシュは、静的ランダムアクセスメモリ(SRAM)ハードウェア技術と呼ばれます。
キャッシュローカリティの原則:プログラムは、ローカルエリアのデータとコードにアクセスする傾向があります。したがって、キャッシュメモリは、プロセッサが近い将来必要になる可能性のある情報を格納するための一時的なステージング領域として機能します。
ストレージデバイスの階層
上から下に向かって、デバイスのアクセス速度はどんどん遅くなり、容量はどんどん大きくなり、バイトあたりのコストは安くなっています。レジスタファイルは、階層構造の最上位にあります。これは、0レベルであるか、L0として示されます。
メモリ階層の主な考え方は、上位のメモリが下位のメモリのキャッシュとして使用されることです。したがって、レジスタファイルはL1キャッシュ、L1はL2キャッシュ、L2はL3キャッシュ、L3はメインメモリキャッシュ、メインメモリはディスクキャッシュです。
オペレーティングシステム管理ハードウェア
オペレーティングシステムは、アプリケーションとハードウェアの間に挿入されるソフトウェアの層です。ハードウェアを操作しようとするすべてのアプリケーションは、オペレーティングシステムを通過する必要があります。
オペレーティングシステムには2つの基本的な機能があります。(1)制御不能なアプリケーションによるハードウェアの悪用を防止します。(2)複雑で多くの場合非常に異なる低レベルのハードウェアデバイスを制御するためのシンプルで一貫したメカニズムをアプリケーションに提供します。
オペレーティングシステムは、いくつかの基本的な抽象概念(プロセス、仮想メモリ、およびファイル)を通じてこれら2つの機能を実装します。ファイルはI / Oデバイスの抽象表現であり、仮想メモリはメインメモリとディスクI / Oデバイスの抽象表現です。 、プロセスは、プロセッサ、メインメモリ、およびI / Oデバイスの抽象的な表現です。
プロセスとスレッド
プロセスは、オペレーティングシステムによる実行中のプログラムの抽象化です。1つのシステムで複数のプロセスを同時に実行でき、各プロセスはハードウェアのみを使用しているようです。同時操作とは、あるプロセスの命令と別のプロセスの命令がインターリーブされることを意味します。
コンテキスト:オペレーティングシステムは、プロセスの実行に必要なすべての状態情報(PC値、メインメモリコンテンツなど)を維持および追跡します。
コンテキスト切り替え:オペレーティングシステムは、インターリーブ実行を実現するためにプロセスを切り替えるようにプロセッサを制御します。
あるプロセスから別のプロセスへの移行は、オペレーティングシステムカーネルによって管理されます。カーネルは、オペレーティングシステムコードのメインメモリ部分です。カーネルは別個のプロセスではありません。むしろ、それはすべてのプロセスを管理するためにシステムによって使用されるコードとデータ構造のコレクションです。
プロセスは、スレッドと呼ばれる複数の実行ユニットで構成されます。各スレッドは、プロセスのコンテキストで実行され、同じコードとグローバルデータを共有します。マルチスレッドは、複数のプロセスよりもデータを共有する方が簡単であり、スレッド間の切り替えのオーバーヘッドは、プロセス切り替えのオーバーヘッドよりもはるかに小さくなります。
仮想メモリ
仮想メモリは抽象的な概念であり、各プロセスに錯覚を与えます。つまり、各プロセスはメインメモリのみを使用します。各プロセスが認識するメモリは一貫しており、仮想アドレス空間と呼ばれます。
上の図は、仮想アドレス空間をいくつかの部分に分割し、矢印を使用してこの部分の拡張方向を示しています。最下位アドレスは0で、上位アドレスは徐々に増加します。各部の機能は以下のとおりです。
プログラムコードとデータ:実行可能なプログラムコードとグローバル変数をコードに保存します。
ヒープ:malloc
関数によって適用される動的メモリ空間など、動的アプリケーションに使用されるメモリ変数を上に拡張できます。
共有ライブラリ: C言語ライブラリ関数のコードとデータを格納するために使用されます。この例のprintf
コードとデータ。
スタック:仮想アドレススペースの最上部にあり、関数呼び出し、ローカル変数の保存などに使用されます。関数を呼び出すと、スタックは下に拡張し、戻ると上に縮小します。
カーネル仮想メモリ:アドレススペースの上部の領域は、カーネル用に予約されています。アプリケーションは、この領域の内容を読み書きしたり、カーネルコードで定義された関数を直接呼び出したりすることはできません。代わりに、これらの操作を実行するためにカーネルを呼び出す必要があります。64ビットオペレーティングシステムの場合、ユーザースペースは0〜3G、カーネルスペースは3G〜4Gです。(ユーザースペースとカーネルスペースの違いは何ですか。秋の募集資料にある組み込みソフトウェアエンジニア向けの書面によるインタビューの知識ポイントの要約を参照してください)
並行性と並列性
同時実行性:同時に、複数のプロセッサで同時に実行される複数の命令があることを意味します。したがって、ミクロまたはマクロの観点から、両方が一緒に実行されます。
平行:それはなく、同時にミクロレベルで、マクロレベルで同時に実行する複数のプロセスの効果を作り、その唯一つの命令を同時に実行することができるが、複数の処理命令を急速回転して実行される、唯一の手段時間複数のプロセスが交互にすばやく実行されるように、いくつかのセクションに分割されています。
マルチコアプロセッサとマルチスレッド
マルチコアプロセッサ:マルチコアプロセッサは、複数のCPU(「コア」と呼ばれる)を集積回路チップに統合します。次の図に示すように、マイクロプロセッサチップには4つのCPUコアがあり、それぞれに独自のL1キャッシュとL2キャッシュがあります。L1キャッシュは2つの部分に分かれています。1つは最後にフェッチされた命令を保持し、もう1つはデータを保存します。これらのコアは、メインメモリへの高レベルのキャッシュとインターフェイスを共有します。
ハイパースレッディング:ハイパースレッディングは、同時マルチスレッディング(同時マルチスレッディング)と呼ばれることもあり、CPUが複数の制御フローを実行できるようにするテクノロジーです。たとえば、Intel Core i7プロセッサでは、各コアで2つのスレッドを実行できるため、4コアシステムでは実際には8つのスレッドを並行して実行できます。
最初のように習慣を身につけてから見てください!文章が良いと思うなら、ワンクリック3接続を歓迎します、ありがとう!
著作権に関する声明:この記事はブロガーの元の記事であり、CC 4.0 BY-SA著作権契約に従います。再印刷するには、元のソースリンクとこの声明を添付してください。
この記事へのリンク:https://blog.csdn.net/qq_16933601/article/details/109169750