Linux カーネル用のロード可能なモジュールを作成しています。ここでは、メモリ ページをマップおよびマップ解除する必要があります。すべての割り込みが無効になっているときに発生します。アクションのシーケンスは次のようになります。
preempt_disable();
disable_all_interrupts(&interrupt_mask_saved);
kmap_atomic(page); // here i map ONE page
do_some_work();
kunmap_atomic(page); // unmapping ONE page
restore_all_interrupts(interrupt_mask_saved);
preempt_enable();
このようなアクションでは、すべてがうまく機能します。しかし、次のようにいくつかのページをマップ/マップ解除する必要がある場合(CPU負荷を改善するために必要です):
preempt_disable();
disable_all_interrupts(&interrupt_mask_saved);
for (i = 0; i < page_num; i++) {
kmap_atomic(page[ i ]); // here i map several pages
}
do_some_work();
// i tried backward unmapping but the result is the same
for (i = 0; i < page_num; i++) {
kunmap_atomic(); // unmapping several pages
}
restore_all_interrupts(interrupt_mask_saved);
preempt_enable();
システムがクラッシュします。エラーおよび情報メッセージは、グラフィック モードでない場合、端末に直接表示されます。画面にいくつかのメッセージを出力した後、システムがフリーズします。カーネル ログは空ですが、私が気付いたエラーは次のとおりです。
scheduling while atomic
thread overran stack or stack corrupted
Linux コードでは、kunmap_atomic よりも preempt_schedule() を使用していることを発見しました。おそらく、これがアトミックなスケジューリングの原因です。しかし、プリエンプションを処理せずに kmap_atomic と kunmap_atomic の独自の関数を書き直しましたが、それでも機能しません。マッピングとマッピング解除の間に行うアクションは原因ではありません。それらを使用せずに試してもフリーズするからです。
Linux カーネル バージョン: 3.0.48、Distr AltLinux 7.0.1 および Altlinux 6.0 カーネル バージョン 3.4.62 は正常に動作しますが、正確には 3.0.48 が必要です
私はしばらくそれに苦労してきましたが、私にはアイデアがありません。あなたがいずれかを持っている?