DAX(ダイレクトアクセス)を見ているうちに、XIP(Execution in Place)を置き換えるために導入されたことを確認しましたが、実際にRAMにコピーせずにアプリケーションを実行できるかどうか疑問です。 「直接アクセスファイル」となっていますが、実行ファイルもカーネルファイルじゃないですか?それでは、カーネルにファイルをRAMにコピーせずにファイルを実行させますか?では、どのように動作しますか? .text領域を保持しますが、.data領域のコピーを作成しますか?
実験的な設定があります。 DAXをサポートするLinuxカーネル4.6.2を設定しました。 RAM対応ブロックデバイスを作成しました。 daxオプションを使用してRAMディスクをインストールします。
# mount -t ramfs -o dax,size=8m ext2 /ramdisk
# mount
rootfs on / type rootfs (rw,size=59124k,nr_inodes=14781)
proc on /proc type proc (rw,relatime)
tmpfs on /tmp type tmpfs (rw,relatime)
ext2 on /ramdisk type ramfs (rw,relatime,dax,size=8m)
#
これでramfsを/ ramdiskにマウントし、ext2とdaxサポートでフォーマットしました。アプリケーションを/ ramdiskにコピーして実行している場合は、RAMの別の場所にコピーして実行しないようにするにはどうすればよいですか?
残念ながら、daxに関する文書はまれです。それカーネルの説明説明する:
メモリに似たブロックデバイスの場合、ページキャッシュページは元のストレージの不要なコピーになります。 DAXコードは、ストレージデバイスに直接読み書きすることで、追加のコピーを削除します。ファイルマッピングの場合、ストレージデバイスはユーザー空間に直接マッピングされます。
実行可能ファイルをRAMの2番目の場所にコピーせずに実行できるようです。しかし、一部の人々はこう言います。
カーネルまたはそのモジュールがDAX対応ブロックデバイスのDAX対応ファイルシステムに保存されていても、RAMにコピーされます。
とにかく私はDAX機能を混乱させ、アプリケーションをRAMの別の場所にコピーせずに実行する方法を提供できるかどうか疑問に思います(キャッシュにコピーすることは私の主題ではありません)。どのように動作するかについての説明を聞きたいです。
答え1
あなたの例を議論する前に、いくつかの免責事項があります。これは現実の単純化されたバージョンです。私が説明していない多くの特別なケースや例外がありますが、何が起こっているのかを理解するのに十分です。
ブロックデバイス
あなたを混乱させるのは、「ブロックデバイス」という用語を誤用することです。ブロックデバイスは通常HDD、CD、SSDです。名前が示すように、これらのデバイスには個々のバイトを読み書きすることはできず、ブロック(通常は512バイトサイズ)で書く必要があります。
ブロックデバイスには、デバイスの状態を読み取って命令を送信するために使用できるプロセッサアドレス空間にマッピングされた複数のレジスタと小さなメモリ領域があります。ただし、(通常)自分が保存したデータへの直接アクセスは提供されません。これは通常、デバイスにコマンドを送信し、DMA操作(読み取りまたは書き込み)が完了したことを示すハードウェア割り込みを待つように行われます。
したがって、このタイプのデバイスにはそのタスクにDMAタスクなどが含まれているため、メインメモリ(DRAM)を使用しないのはかなり困難です(不可能ではありません)。そのような場合、DAXが実行する作業は、データアクセスに関連するオーバーヘッドの一部を削除することだけです。
DIMMフォーマット* NVM
しかし、最近では、一部のDIMMフォーマット* NVM(不揮発性メモリ)が市場に出荷されました。これらのデバイスには、アクセスできるようにコンテンツ全体がプロセッサのアドレス空間にマッピングされています。まっすぐストアとロード命令を介してプロセッサによって。カーネルは、これらのデバイスがアクセスされていることを知る必要さえありません。すべての意図と目的のために、プロセスは通常のDRAM対応メモリページにアクセスするようです。
*DIMM形式は一例です。 PCIなどの他の既存のインターフェースもこれを行います。
混乱した部分
ここに混乱があります...最近まで、「ストレージデバイス」は実際に「ブロックデバイス」の同義語でした。 Linuxカーネルはこれらの新しいNVMをストレージ/ブロックデバイスとして認識し、SSDと同様に/ devにエントリを作成して適切に処理します。 (これらのNVM対応デバイスの1つがない場合は、通常のDRAMの特定のメモリ範囲をNVMとして処理するように指定してこれをエミュレートできます。ねえこれを行う方法に関する追加情報。 )
これらのデバイスにファイルシステムを作成すると、通常のHDDを使用しているかのように機能します。コンテンツをDRAMにキャッシュしてパフォーマンスを向上させようとしています。 DAX 対応ファイルシステムが実行する作業は、キャッシュの生成を防止することです。これはアクセスを高速化するためのものですが、この場合はパフォーマンスが低下する可能性があります。
カーネルまたはそのモジュールがDAX対応ブロックデバイスのDAX対応ファイルシステムに保存されていても、RAMにコピーされます。
この動作の明確な理由を見つけることはできませんが、カーネルとカーネルモジュールが遅い(DRAMよりも遅い)デバイスで実行されず、その内容が次に実行されることを保証するのはセキュリティとパフォーマンス上の理由のようです。カーネル期間はめちゃくちゃになりません。
ただし、NVM対応メモリを使用してNVMから直接実行可能ファイルを実行している限り、ユーザースペースに残っている限り問題はありません。
プロジェクトを見てくださいPmem.ioインテルとアトラスHPから。この種の作業のために特別に作成されたプログラミングインターフェイスです。
今あなたの例について:
# mount -t ramfs -o dax,size=8m ext2 /ramdisk
# mount
rootfs on / type rootfs (rw,size=59124k,nr_inodes=14781)
proc on /proc type proc (rw,relatime)
tmpfs on /tmp type tmpfs (rw,relatime)
ext2 on /ramdisk type ramfs (rw,relatime,dax,size=8m)
#
RAM サポート EXT2 ファイルシステムを作成していません。仮想名がext2のramfsを使用してRAM対応ファイルシステムを作成しています。次のようにインストールしても違いはありません。
# mount -t ramfs -o dax,size=8m winter_is_coming /ramdisk
答え2
.text領域を保持しますが、.data領域のコピーを作成しますか?
とにかくexec()
同じように動作します。これらのページは、プロセスの仮想アドレス空間に読み取り専用にマップされます。したがって、書き込みによりページフォルト割り込みが発生します。これらのページフォルト処理は、次のように説明されます。mmap()
MAP_PRIVATE
書き込み中のコピー。
DAXの場合、仮想ページは最初にデバイスの物理ページにマップされます。ただし、MAP_PRIVATEの書き込みページエラーは、ページデータをRAMの新しいページにコピーします。 (これにより、プロセスのマップがそれに応じて更新され、中断されたプログラムコマンドが再起動されます。)
DAXは、書き込みと読み取りの両方を許可するXIP、つまりMAP_SHAREDとMAP_PRIVATEの一般化です。たとえば、MAP_SHAREDはデータベースファイルに使用できます。
実際には.text
共有ライブラリに作成することもできます。場所に依存しない実行可能ファイルではなく、自身への参照を含むライブラリーは、依存ライブラリーがロードされるアドレスに基づいてその参照を更新する必要があります。この過程を「再配置」といいます。ライブラリは、libcなどの他のライブラリも参照します。これらの参照を更新することを「記号の確認」と呼びます。
カーネルまたはそのモジュールがDAX対応ブロックデバイスのDAX対応ファイルシステムに保存されていても、RAMにコピーされます。
カーネルモジュールは特別です。また、記号の確認が必要です。ただし、カーネルはCOWを使用しません。 (より一般的には、そのコードとデータセグメントはリクエストページングを使用しません。)カーネル内のページエラーは、これを処理すると無限の再帰につながる可能性があるため、致命的です。したがって、DAX以前はカーネルモジュールをRAMに完全にコピーする必要があることは明らかでした。カーネルコードとデータセグメントは小さいです。 DAXが実装されている場合は、バイトアドレス指定可能なストレージを持つサーバーで変更しても利点はありません。
カーネル自体は歴史的に圧縮されており、明らかにRAMで解凍されました。
つまり、XIPははいサポート圧縮されていないカーネルの場合。これは通常、「組み込み」システム、つまり非常に限られたハードウェアに使用されます。この時点で、ロード可能なモジュールを使用するのに比べて必要なコードの大部分を構築することは問題にならないかもしれません。