Linuxカーネルからメモリブロックを予約するにはどうすればよいですか?


25

OSを介さずに、専用のメモリブロックを必要とするデバイスがあります。メモリブロックが予約されていることをBIOSまたはOSに伝える方法はありますか?

このデバイスをopenSUSEマシンで使用しています。

回答:


23

あなたが求めているのはDMAと呼ばれるものです。このメモリを予約するには、ドライバを作成する必要があります。

はい、OSに介入したくないと言い、ドライバーがOSの一部になりますが、ドライバーの予約がない場合、カーネルはすべてのメモリがそれに属すると信じています。(カーネルにメモリブロックを無視するように指示しない限り、アーロンの答えによると、つまり)

Rubini、Corbet、およびKroah-Hartmannによる「Linux Device Drivers、3 / e」の第15章(PDF)は DMAおよび関連するトピックをカバーしています。

このHTMLバージョンが必要な場合は、オンラインでこの章の第2版を見つけまし。カーネル2.4が新しくなったときに出てきて、第2版が10年以上前になっていることに注意してください。当時のカーネルのメモリ管理サブシステムには多くの作業が行われていたため、これ以上適用されない可能性があります。


DMAでは、使用する物理アドレスを選択できますか?カーネルは連続したメモリブロックを提供しますか?常に利用できることが保証されていますか?
ネイサンフェルマン

1
あなたの質問は、私が指摘したPDFの442ページから始まります。
ウォーレンヤング

24

OSで完全に無視する場合は、memmap「」を使用してメモリホールを作成する必要があります。このリファレンスを参照してください。たとえば、2GBの障壁で512Mが必要な場合memmap=512M$2Gは、カーネルコマンドラインに " "を配置できます。

dmesg盗む連続した穴を見つけるためにあなたをチェックする必要があります従ってあらゆるデバイスで踏みつけないため; それは、マザーボードとカードに固有です。

これは物事を行うための推奨される方法ではありません -それを適切に行う方法についてはウォーレンヤングの回答を参照してください(カーネルドライバー+ DMA)。あなたが尋ねた正確な質問に答えています。エンドユーザー向けにこれを作成する予定がある場合、エンドユーザーにこれを行うと、彼らはあなたを嫌います...私を信頼してください。


編集:grub2 w / grubby(CentOS 7など)を使用している場合は、必ず$をエスケープする必要があります。単一の\前にある必要があり$ます。例:

$ sudo -v
$ sudo grubby --update-kernel=ALL --args=memmap='128M\\$0x57EF0000'
$ sudo grubby --info $(sudo grubby --default-kernel) | grep memmap
args="ro crashkernel=auto ... memmap=128M\$0x57EF0000"

1
あなたの答えは私の質問に直接答えますが、ウォーレンの答えはそれを進めるより良い方法のようです。:
ネイサンフェルマン

1
@WarrenYoung私は持っていない何もあなたがそれを行うことになっているもののアイデアを。uint8_t *ptr = 0x8000000私の例では「」と思いますか?または、それはセグメンテーション違反の可能性があります...ええと、私は本当に知りません。繰り返しになりますが、私は貧弱に設計されたPCIカードのエンドユーザーであり、4Gマークより下に手動でバッファーを割り当て、そのスペースがどこにあるかをドライバーに伝える必要があるため、答えを知っていました。ユーザーランドからは不可能な場合があります。
アーロンD.マラスコ

2
にやにや笑いのために、私はこれをもう少し詳しく調べましたMMAP_FIXED | MMAP_ANON。ここにカスタムDMAデバイスがなければ、OPが実際に望んでいたことを実行できるかどうかはわかりませんが、memmap=8M$512MGRUBで言ったとき、CentOSボックスは512 MBで8 MBブロックを喜んでくれました。私は恐れていたので、ルートアクセスさえ必要としません。しかし、これが正しいことをしたとしても、おそらく割り込みなどを処理するためにドライバーが必要になると思います。
ウォーレンヤング

3
@ AaronD.Marasco:いいえ、mmap()「d」ページはユーザーランドコードがそれらを見る前にゼロにされます。セキュリティのために行われているため、あるプロセスから次のプロセスにデータが漏れることはありません。ドライバーを使用するもう1つの理由は、ドライバーのロード時にDMAバッファーの内容を保持する必要がある場合があるためです。ああ、ところで、任意の場所に配置されたmmap()呼び出しは、memmapカーネルブートオプションがなくても成功します。少なくとも、要求した場所にあるメモリを誰も使用していない限りです。ブートオプションは間違いなく成功の可能性を高めますが、必ずしも必要ではありません。
ウォーレンヤング

1
@ AaronD.Marascoうーん、わかりました。面白い。そのリンクをありがとう、それは良い読み物です。
ウッド

5

ARMベースのLinuxのカーネルからメモリブロックを予約するにreserved-memoryは、デバイスツリー(dts)ファイルのノードを使用することもできます。カーネルのドキュメント(こちらをご覧ください)に例があります:

memory {
    reg = <0x40000000 0x40000000>;
};

reserved-memory {
    #address-cells = <1>;
    #size-cells = <1>;
    ranges;

    /* global autoconfigured region for contiguous allocations */
    linux,cma {
        compatible = "shared-dma-pool";
        reusable;
        size = <0x4000000>;
        alignment = <0x2000>;
        linux,cma-default;
    };

    display_reserved: framebuffer@78000000 {
        reg = <0x78000000 0x800000>;
    };

    multimedia_reserved: multimedia@77000000 {
        compatible = "acme,multimedia-memory";
        reg = <0x77000000 0x4000000>;
    };
};

0

最初にこのコマンドを入力して、現在の設定を確認します。

sysctl vm.min_free_kbytes

設定値を変更するには、を編集します/etc/sysctl.conf。次の行を探します。

vm.min_free_kbytes=12888

存在しない場合は、(目的の値とともに)作成します。次の値が許容されます。

8192
12288
16384
20480

8Mは非常に保守的です。16Mで快適に座ることができます。値を変更したら、これを実行すると、再起動は不要です。

sudo sysctl -p

2
投稿を空白にしないでください。削除するか、モデレーターが削除するようにフラグを立ててください。
ジェイソンライアン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.