1

:) 一部のレガシー コード (大規模なプログラム) を CentOS 7 に移植しようとしていますが、問題が発生しています。コードのコアは、ハードコードされたアドレスを割り当て、ファイルをそれにマップするために mmap を使用して構築された、やや厄介な構造です。このファイルはデータベースのように機能し (データベースによって構築されます)、マップされたメモリのさまざまなセクションへのハードコーディングされたポインターが含まれています。非常に醜いですが、それはそれです。プログラム全体はこの構造を中心に構築されており、誰も書き直しに資金を提供するつもりはありません。

問題は mmap 行にあります。これは以前は機能していましたが、CentOS 7 では機能しなくなりました。

mmapAddr = mmap ((void *) SMAddr, SMA_WINDOW_SIZE, PROT_READ | (readOnly ? 0 : PROT_WRITE),MAP_FILE | MAP_FIXED | MAP_SHARED, SMFileDesc, 0);

...SMAddr0x8000000SMA_WINDOW_SIZE127926272readOnlyは false です。0x8000000つまり、基本的には、ファイルをサイズ 122MBのアドレスにマップしようとしています。

バージョン間で何が変わったのか、私にはわかりません。ただし、マッピングするファイルはわずか 1.5 MB であることに注意してください。なぜファイルサイズよりも多くをマップする必要があるのか​​ 正確にはわかりませんが、それが必要であることはわかっています.

実際のファイル サイズと割り当てられたサイズの不一致は、以前は問題ありませんでしたが、今は問題ありませんか? SIGBUSこれは、無効なメモリ領域にアクセスしようとしていることを意味します。mmap が割り当てられたポインターをまったく使用しないことを考えると、これは内部で行っているものでなければなりませ

キャッチしてブロックしようとしSIGBUSましたが(無視できるのではないかと思いますか?)、プログラムはまだSIGBUS同じ場所でクラッシュしました。多分私はそれを間違った。

考え?

4

1 に答える 1

3

ここから1 :

mmap() 関数を使用して、オブジェクトの現在のサイズよりも大きいメモリ領域をマップできます。マッピング内ではあるが、基礎となるオブジェクトの現在の終端を超えたメモリアクセスにより、SIGBUS シグナルがプロセスに送信される可能性があります。これは、オブジェクトのサイズが他のプロセスによって操作され、いつでも変更される可能性があるためです。実装は、メモリ参照が、これを検出できるオブジェクトの外部にあることをアプリケーションに通知する必要があります。そうしないと、書き込まれたデータが失われ、読み取られたデータがオブジェクト内の実際のデータを反映していない可能性があります。

ほとんどの仮想メモリ ハードウェアでは新しい終了を正確に判断できないため、オブジェクトの終了を超えた参照はオブジェクトを拡張しないことに注意してください。代わりに、サイズは ftruncate() によって直接操作できます。

したがって、最も可能性の高いバグは、プログラムがファイルの外側にあるマップされたメモリの領域にアクセスしようとすることです。ただし、mmap 呼び出しは成功するはずです。どの戻り値が得られますか?

于 2016-08-15T18:03:59.193 に答える