低レベルのトピックに関する知識は多かれ少なかれ0なので、無知であることを許してください。
Cなどの言語では、ポインタが「メモリアドレス」、つまり0x52A132F3
などの16進数で記述された文字列(またはバイナリデータ?)を保持することを知っています。
「メモリアドレス」という用語から判断すると、この数は実際にはメモリ内のある場所につながると思います。しかし、「メモリ内の場所」が実際に何であるか、および16進数がそれにどのように「つながる」かを理解するのに苦労しています。 (A Javaプログラマはここにいます。)
したがって、2つの質問:
0x52A132F3
などの「序数」番号を使用してメモリを参照する意味があるように、メモリはハードウェアで「順序付け」されていますか?ハードウェアでのメモリの順序付けはどのように行われますか。また、数値を使用してメモリにアクセスすることがどのように、そしてなぜ意味があるのでしょうか。ポインタはメモリアドレスを参照することがよくありますが、概念自体は別のものです。私は、メモリアドレスの根本的な「低レベル」の概念に焦点を当てます。
メモリアドレスは、CPU自体、またはコンピューター内の任意の場所を指していますか?
メモリアドレスという用語は、おそらくCPUのオンボードメモリの一部を指しますが、この場合はそうではありません。
これらのアドレスは、通常はRAMであるコンピューターの一般的な「メモリ」を指しますが、最近のOSでは、物理メモリまたは実際に他の場所に移動する仮想メモリとして抽象化される場合があります。また、メモリアドレスがビデオカードまたはその他のハードウェアのメモリオフを参照していることもときどきあります。
0x52A132F3などの「通常の」番号を使用してメモリを参照するのに意味のある方法で、メモリはハードウェアで「順序付け」されていますか?
はい。
メモリが厳密に隣接していない場合でも(RAMのさまざまなチップに加えて、上記の物理/仮想メモリを参照)、ハードウェアとOSがそれを次のようなものに抽象化します 無限に長いテープ 。それは、線形にアドレス可能な順序付けられたメモリです。
各アドレスには、保存できる一定量のデータが含まれます(バイトは一般的ですが、ユニバーサルではありません!)。もちろん、さまざまなアドレッシングスキームが可能ですが、コンピューターは整数計算を行うのに本当に良いので、非効率的です。
マザーボードには、CPUと、RAMに接続する多数のワイヤ(バスと呼ばれます)があり、比較的簡単に交換できるスティックに個別に付属しています。メモリアドレスは、これらのワイヤの32を制御していると考えることができます。 0x52A132F3
は、バイナリでは01010010101000010011001011110011
に変換されます。各1
は、CPUが対応するワイヤーに電圧(DDR3では1.5ボルト)をかけることを意味し、RAMチップにどのメモリをCPUに送り返すかを通知します。
これは、キャッシュや仮想メモリページなどの理由で単純化しすぎており、システムは4 GBのRAMをサポートしている場合があり、アドレスワイヤの数も増減する可能性がありますが、メモリアドレスについて考えるための有用なモデルであり、よりシンプルです。組み込みシステムはそのように機能します。
16進数が使用されるのは、32ビットの数値の場合、先頭のゼロを含めて常に8桁であるためです。バイナリへの変換も簡単です。また、0xDEADBEEF
や0xABBACAFE
などのクールなアドレスを記述できます。これらは、デバッグに役立つ場合があります。ほとんどの場合、それはシステム上のすべてのメモリの非常に大きな配列へのインデックスと考えることができます。
まず、ポインタにメモリアドレスが含まれていることは、実装の詳細です。それはそれが標準で定義されている方法ではありません。標準は非常に機能しますveryハードウェアに関して曖昧にするのは難しいので、Cは最も奇妙で最もエキゾチックなアーキテクチャで実行できます。たとえば、異なる型の2つのポインターが同じ表現(char*
とvoid*
を除く)であると仮定したり、オブジェクトへのポインターが関数へのポインターと同じ表現であると仮定することはできません。
実際の質問に対処するには:
つまり、メモリをバイトの配列と見なし、メモリアドレスをその配列へのインデックスと見なすだけです。
*はい、CPUにキャッシュがあることは知っています。
これをもっと単純な例えにしよう。手紙を送る場合は、封筒に住所を記入して、郵便ポストに入れます。しかし、それは実際にはどのように特定のアドレスに送信されるのでしょうか。 PostMan(または配達人)は実際に、封筒に書かれた数行がどの物理的な場所を向いているのかを知っています(個人的にその場所に行ったことがないと仮定します)。
CPUも同じように動作し、メモリアドレスを使用して、処理する必要のあるデータを取り込みます。ここで、メモリとはRAM(ストレージCPUはデータの処理を指します)を指します。CPUには、それ自体がレジスタと呼ばれる処理を実行するために使用するメモリもあります。メモリアドレスを使用してランダムにアクセスできます。メモリ内のアイテムを取得するためにループしたり、1つずつ移動したりすることはできません。
1.メモリアドレスは、CPU自体、またはコンピューター内の任意の場所を指していますか?
いいえ。最新のすべてのオペレーティングシステムでは、 仮想アドレススペース が使用されます。各プログラムには独自のアドレス空間があります。ポインタ値は、このアドレス空間のアドレスです。このアドレス空間のアドレスは、OSのメモリマネージャーによって物理メモリにマップされます。
このマッピングはスパースです。必要なアドレスのみがマッピングされます。さらに、一部のアドレスは物理メモリにマップできません(セグメンテーション違反または一般保護エラーを考えてください)。
このマッピングは揮発性です。同じアドレスが異なる時点で物理メモリの異なる部分を指す場合があります。
2.
0x52A132F3
などの「通常の」番号を使用してメモリを参照するのに意味のある方法で、メモリはハードウェアで「順序付け」されていますか?
プログラムが信頼できる方法ではありません。メモリマネージャは、適切と思われる方法でこれらのアドレスをマップできます( 仮想メモリ を参照)。
ハードウェアでのメモリの順序付け方法
コンピュータによって、物理メモリの設定方法は異なります。設定は、メモリマネージャにとって意味のあるものである必要があります。
そして、数値を使用してそれにアクセスすることはどのようにそしてなぜ意味があるのですか?
アドレスによって使用される数値は、物事をより簡単にします。配列について考えてみましょう。数値アドレスを使用すると、ベースアドレスとインデックスを追加するだけで、特定のインデックスの値を簡単に検索できます(これは、ほとんどの言語が0から始まる配列を持っている理由です)。
このベースアドレスとインデックスの計算は、オフセットと呼ばれます。オフセットは、構造体からフィールドを取得したり、関数のパラメーター値を取得したり、ループしたり、分岐したりするために使用されます。数値アドレスなしで計算がどのように行われるかを想像できません。
手紙を郵送することは、これを説明するための最善の方法です。名前、番号、通り、町、郵便番号、スイート番号など、住んでいる場所によって異なります。
手紙は、このすべての情報が記載された状態で家を出ます。郵便局は、これらのアイテムを最初に家から出て、次に、郵便局を出ているか、この町を出ているかなど、大まかに把握するための最初のレベルの検査を行います。その通り/地域の郵便担当者にそれを届ける方法に沿って決定と並べ替えを行い、家ごとに並べ替えて配達します。
プロセッサーとプログラマー(あなたは間接的ですが、オペレーティングシステムからかなりの量の助けを借りています)はあなたの家にいて、物へのアドレスの参照資料(アドレス帳)を持っています(オペレーティングシステムは必ずしもそうではないあなた)これらのもののいくつかは単にramであり、いくつかは周辺機器または制御およびステータスレジスタなどです。この平らなアドレススペースが存在するプロセッサまたは外部に境界があります。その境界は家と縁石のメールボックスの間の庭です。アドレスがこのバスにトスされてポストマンが引き継ぎ、ロジックのレイヤーがアドレスを選択して、チップに戻る必要がある場所、またはボード上の周辺機器やメモリに戻る必要がある場所を決定します。
したがって、一般的にyesのアドレスは、CPU内のものとCPU外のものを指すことができます。ハードウェア設計者は通常、作業を過度に困難にしたくないので、通常、アドレスの連続したビットの1つまたはチャンクを使用してトランザクションをルーティングします。たとえば、一部の上位ビットはオンチップまたはオフを決定し、次に次のビットダウンはペリフェラルからのRAMを決定し、ペリフェラルにルーティングされると、さらにいくつかのビットダウンがペリフェラルのどこを決定するかもしれません。 lspciを実行してアドレス範囲を確認するギャップもあります。ペリフェラルが32MBを必要とするからといって、32MB相当の個別の話ができるとは限らないので、ロジックが一度に決定を下すのは2のナイスパワーにすぎません。ペリフェラルは、これらのビットを使用して少数のものまたは効率的なものにアクセスすることを選択した場合、無駄になる可能性があります。
ここでも、階層化されたオペレーティングシステムは、そのボードとプロセッサに関する直接的または間接的な知識を備えており、通常はユーザーからそれを隠します。通常、UARTレジスタを突っ込むだけではなく、カーネル関数を呼び出すアプリケーション層で関数を呼び出します。やがて、信号がuartやその他のインターフェース上で小刻みに動くレジスタに到達します。 1つの仮想化アドレスがあり、アプリケーションまたはすべてのアプリケーションが0x0000のようなアドレスから開始し、0x000からNバイトのメモリを搭載しているように感じる場合、すべてのプログラムを同じ方法でコンパイルできますが、ハードウェアでの変換とソフトウェア(オペレーティングシステム)は、0x1234のアドレスを他のアドレスに変換してから、家を出て魔法の境界に到達し、郵便局のドメインのメールボックスに到達するようにします。