0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

cpuのbyte orderの影響範囲と具体例

Posted at

例1: レジスタ上に存在する1バイトの0000_0001をメモリに乗っけると0000_0001のままである.
例2: レジスタ上に存在する2バイトの0000_0001 0000_0010をメモリに乗っけると0000_0010 0000_0001の並びで配置されます
例3: レジスタ上に存在する4バイトの0000_0001 0000_0010 0000_0011 0000_0100をメモリに乗っけると0000_0100 0000_0011 0000_0010 0000_0001の並びで配置されます

この様に、レジスタからメモリに移す際に反転される.

参考: https://qiita.com/tobira-code/items/a03f39a02678d80bbd26

ext4のブロックに書き込む際

ext4のすべてのフィールドは、リトルエンディアンの順序でディスクに書き込まれます。ただし、jbd2(ジャーナル)のすべてのフィールドは、ビッグエンディアンの順序でディスクに書き込まれます。

参考: https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout

理由の考察:
そもそも項目毎にリトルエンディアンとして書き込まないと駄目な理由は、ext4自体は項目毎に読み込んで、読み書きする.
ブロックへの書き込みも、ブロックサイズ未満の書き込みでも、ext4自体はブロックを読み込み、ブロック単位で書き込みをしている. その際に、メモリ上で読み込んだデータと今回書き込むデータを合成し、ブロック単位で書き込んでいるので、以下のAの様にはならず、Bの様に保存できる.

A:
0000_0001 0000_0010を書く. 続く所から0000_0011 0000_0100を書く.
実際: 0000_0010 0000_0001 0000_0100 0000_0011 ...
これは間違い

B:
0000_0001 0000_0010を書く. 続く所から0000_0011 0000_0100を書く.
実際: ... 0000_0000 0000_0000 0000_0000 0000_0000 0000_0100 0000_0011 0000_0010 0000_0001
の様に後ろから書き込まれていく.
これは正

通信する際

ネットワークプロトコルはビッグエンディアンだけを使う.

送る際にはhtonl
受け取る際にはntohl
で、エンディアン変換を行う. (ビッグエンディアンのCPUの場合は、何も処理が行われない. リトルエンディアンのCPUの場合だけ、byte orderが逆になる.

参考: https://www.jpcert.or.jp/m/sc-rules/c-pos39-c.html

理由

リトルエンディアンの規格のCPUの場合、メモリの並び順はCPU外部からみた際には、リトルエンディアンである.
レジスタの並び順はビッグエンディアンである. (レジスタはCPUからしか触れないけど.
メモリは共有資源であり、ストレージやネットワークデバイスは、メモリバス経由でメモリを読んだり書いたりする.
また、ストレージやネットワークデバイスはmemory-mapped i/o経由で操作される.
send_to syscallには、メモリ上に存在するbufferのアドレスと送信する長さを指定する.
リトルエンディアン規格のCPUの場合だと、メモリの中に存在するbuffer並び順はリトルエンディアンである.
ネットワークデバイスは指定されたアドレス値の中身を順番に送信していく為、リトルエンディアンの並び順のままだと受け取り側が正しく復号化できないので、TCP/IPプロトコルに沿ってビッグエンディアンの並び順になるようにメモリの状態を変更してから送る.
同様にビッグエンディアンの並び順で受信側は届くので、リトルエンディアンの並び順に変更してからデータを操作する必要がある.

補足すると、レジスタからメモリに配置する際に反転するので、structなら要素単位、固定長配列なら、要素単位で反転する.なので、もしstructの各要素をビッグエンディアンに並べ替えたい場合は、それぞれの要素に対してhtonlをする必要がある. また、固定長配列の要素をビッグエンディアンに並べ替えたい場合は、全要素にhtonlをする必要がある. これが必要になるケースは、バイナリをネットワーク経由でやりとりする際だが、ここまで来ると最適化の為に、ネットワーク経由でリトルエンディアンのままでのやりとりや保存とかもしそうだと思いました.

その他参考資料

https://jp.quora.com/ippan-teki-ni-ritoru-en-de-i-an-deha-naku-biggu-en-de-i-an-ga-saiyou-sa-re-te-iru-riyuu-ha-nanda-to-omoi-masu-ka
https://www.intel.co.jp/content/dam/www/public/ijkk/jp/ja/documents/developer/IA32_Arh_Dev_Man_Vol2A_i.pdf
https://blog.framinal.life/entry/2021/06/15/235343?utm_source=feed
https://www.cs.uic.edu/~jbell/CourseNotes/OperatingSystems/13_IOSystems.html
https://gist.github.com/yegle/4560621

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?