5

最近のLinuxカーネル(3.4.4)用にコンパイルしようとしている非常に大きなドライバーモジュールがあります。insmod2.6.27.25カーネルで同じモジュールを正常にコンパイルできます。GCCのバージョンも異なり、4.7.0と4.3.0です。このモジュールは非常に複雑であり、すべてのコードとすべてのmakefileを単純に調べることはできないことに注意してください。

モジュールを「挿入」するとCannot allocate memory、次のトレースが表示されます。

vmap allocation for size 30248960 failed: use vmalloc=<size> to increase size.
vmalloc: allocation failure: 30243566 bytes
insmod: page allocation failure: order:0, mode:0xd2
Pid: 5840, comm: insmod Tainted: G           O 3.4.4-5.fc17.i686 #1
Call Trace:
 [<c092702a>] ? printk+0x2d/0x2f
 [<c04eff8d>] warn_alloc_failed+0xad/0xf0
 [<c05178d9>] __vmalloc_node_range+0x169/0x1d0
 [<c0517994>] __vmalloc_node+0x54/0x60
 [<c0490825>] ? sys_init_module+0x65/0x1d80
 [<c0517a60>] vmalloc+0x30/0x40
 [<c0490825>] ? sys_init_module+0x65/0x1d80
 [<c0490825>] sys_init_module+0x65/0x1d80
 [<c050cda6>] ? handle_mm_fault+0xf6/0x1d0
 [<c0932b30>] ? spurious_fault+0xae/0xae
 [<c0932ce7>] ? do_page_fault+0x1b7/0x450
 [<c093665f>] sysenter_do_call+0x12/0x28
-- clip --

明らかな答えは、モジュールが割り当てているメモリが多すぎるということのようですが、次のようになります。

  • このモジュールのサイズに関係なく、古いカーネルバージョンには問題はありません。
  • このモジュールの一部を整理してメモリ消費量を大幅に削減すると、新しいカーネルでも常に同じエラーメッセージが表示されます。
  • 他の多くのモジュールをアンロードできますが、影響はありません(とにかく関連性がありますか?モジュールごとの合計メモリ使用量に関してLinuxにグローバルな制限があります)

したがって、限られたメモリに直接関係しない新しいカーネルに問題があるのではないかと疑っています。

新しいカーネルは約30,000KBvmalloc()の不満を言っていますが、古いカーネルでは、lsmodは4,800KBのサイズを提供します。これらの数字は直接関連している必要がありますか?ビルド中に問題が発生し、要求されているRAMが多すぎる可能性はありますか?両方のセクションサイズをコンパイルすると、.ko大きな違いは見られません。

だから私は問題がどこから来ているのかを理解しようとしています。ダンプされたスタックを確認すると、一致するコードが見つかりません。からの障害vmalloc()は、によって行われsys_init_module()ているようinit_module()ですkernel/module.c。しかし、コードは一致しません。からオブジェクトコードを確認する.koと、init_module()コードも一致しません。

カーネルを十分に理解していないため、多かれ少なかれブロックされており、すべてのビルドシステムとモジュールのロードを理解するのは非常に困難です。一部の関数が欠落していると思われるため、モジュールがロードされる前にエラーが発生insmodし、この時点ではこれらのエラーは報告されません。

4

2 に答える 2

5

割り当てはで行われると思います。layout_and_allocateこれはによって呼び出されload_moduleます。どちらも静的関数であるため、インライン化されている可能性があり、したがってスタック上にはありません。
つまり、これはコードによって行われる割り当てではなく、コードをロードするためにLinuxによって行われる割り当てです。

古いカーネルが4.8MBで、新しいカーネルが30MBの場合、失敗する理由を説明できます。
だから問題は、なぜそれがそんなに大きいのかということです。

サイズは、コードの量(コードがそれほど大きくなっていない可能性が高い)または静的に割り当てられたデータが原因である可能性があります。
考えられる理由は、静的に割り当てられた大きな配列があり、そのサイズはLinuxで定義されていることです。サイズが大幅に大きくなると、アレイも大きくなります。
推測-サイズが。の配列NR_CPUS

nmまたはなどのコマンドを使用objdumpして、そのような配列を見つけることができるはずです。ただし、正確にどのように行うかはわかりません。

于 2012-07-19T13:14:09.903 に答える
2

この問題は、実際にはモジュールのデバッグ セクションが原因でした。古いカーネルはこれらのセクションを無視できましたが、新しいカーネルは割り当てる合計サイズにそれらをカウントしていました。ただし、pr_debug()ロード時に module.c からのトレースを有効にすると、これらのセクションは他のセクションと一緒にダンプされませんでした。

それらを取り除き、問題を解決する方法:

objcopy -R .debug_aranges \
    -R .debug_info \
    -R .debug_abbrev \
    -R .debug_line \
    -R .debug_frame \
    -R .debug_str \
    -R .debug_loc \
    -R .debug_ranges \
    orignal.ko new.ko

このプロジェクトの特定のビルド ファイルが、古いカーネル バージョン用に「調整された」デバッグ情報を追加していた可能性もありますが、ダミー モジュールを試してみると、まったく同じ種類のデバッグ セクションが追加されていることがわかりました。カーネルまたは Fedora でのモジュール管理に関するポリシーの変更。

これらの変更に関する情報は大歓迎です。

于 2012-07-20T11:58:29.100 に答える