要するに、私のプログラムは、ネットワーク パケットを表す raw バイト (u_char) バッファを受け取ります。そのパケット内の情報を解析しようとしていますが、システム定義のヘッダー構造 (ether_header、ip、ip6、tcphdr、udphdr) を使用して解析しています。これを Linux と AIX の両方に実装して動作しましたが、Solaris でこれを実行すると、何らかの理由でバス エラーが発生し続けます。
私がデータを取得する方法は、基本的に、バッファの各部分を構造体の 1 つとしてキャストし、データを読み取ることです。たとえば、私が持っている場合
u_char buffer[] = {...some bytes...};
struct ether_header *ethdr = (struct ether_header *)buffer;
struct ip *iphdr = (struct ip *) (buffer + sizeof(struct ether_header));
etc. etc.
次に、必要な情報を次のように取得できます。
iphdr->ip_v; //to get the version
etc->etc; //to get whatever piece of data I need
通常、Linux と AIX ではこれで問題なく動作します (特定の構造体はシステムによって名前が異なりますが、それは重要ではありません) が、Solaris でこれを実行しようとすると、iphdr->ip_v;
afterになるとバス エラーが発生し続けstruct ip *iphdr = (struct ip *) (buffer + sizeof(struct ether_header));
ます。調査の結果、これはアライメントされていないメモリにアクセスしようとしたことが原因であることがわかりました。イーサネット ヘッダーのサイズはわずか 14 バイトであるため、これは理にかなっています。そのため、IP ヘッダーは配列内でバイト アラインされていません。
これを回避しようとした方法は、関連する部分を別のバッファにコピーしてから読み取ろうとすることでした
memcpy(&buffer_copy, buffer + sizeof(struct ether_header), sizeof(struct ip));
struct ip *iphdr = &buffer_copy;
iphdr->ip_v;
etc.
これは機能しますが、理由がわかりません。memcpy が同じメモリ位置にアクセスしようとしているときにバス エラーをスローしないのはなぜですか? 私は思いついた解決策があまり好きではなく、状況をよりよく理解しようとしているので、何か他のことを考え出すことができます. パズルのピースが欠けているのでしょうか?