ハードウェアを意識したプログラミングの基礎(後編)

荘司靖

前編では,デバイス・ドライバを理解するために必要なエンディアンやI/Oアクセス,ハードウェアとソフトウェアの境界について説明した.後編では,アクセス時のアラインメントについて説明した後,実際のコードを示しながらLinuxデバイス・ドライバの例を紹介する.

(編集部)

1.アクセスは境界に沿って

 エンディアン,I/Oアクセス,ハードウェアの次に問題になるのが,アクセス時のアラインメントです.CPUによってはアラインメントが合っていないアクセスが起こるとエラーになったり,意図しないデータが読めたりします.最後に紹介していますが,実は,知らないと一番見つけづらいところかもしれません.

 まず,「アラインメントが合っていないアクセス」が,どういうものかを定義しましょう.

 ここでは,「アクセスしようとしているアドレス値をアクセス幅で割ったときに,余りが出るようなアクセス」を「アラインメントが合っていない」,または「間違ったアラインメントでのアクセス」と定義します.以降,「unaligned access」と表記します.

 つまり,

  0x1000に4バイトでアクセスはOK
  0x1001に4バイトでアクセスはNG

です.ちなみにどのアドレス値も1バイトでアクセスする場合は余りが出ないので,バイト・アクセス時にアラインメントが合わないということは起こりません.

 では実際のコードで説明します.リスト1のコードはunaligned accessの例です.

1: #include <stdio.h>
2: #include <linux/types.h>
3:
4: int main()
5: {
6:  char fifo[] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0};
7:  __u32 val;
8:  int i;
9:
10:  for (i=0; i<4; i++) {
11:    val = *(__u32 *)(fifo+i);
12:    printf("0x%X\n", val);
13:  }
14:  return 0;
15: }

リスト1 アラインメントが合っていないアクセスを行う

 これを x86で実行してみます.

  $ ./unaligned-x86
  0x78563412
  0x9A785634
  0xBC9A7856
  0xDEBC9A78

 思った通りの値になったでしょうか? 混乱してしまった人は,エンディアンの部分を読み直してみてください.

 さて,それではほかのCPUで実行してみたいと思います.まずは,x86と同じリトル・エンディアンのARMで試してみましょう.最初に使用するボードはArmadillo-9注1です.Armadillo-9のCPUはCirrus Logic社製のEP9315です.EP9315はARMv4アーキテクチャを採用しています.

注1:以下のURLを参照. http://www.atmark-techno.com/armadillo-9

  $ ./unaligned-arm
  0x78563412
  0x12785634
  0x34127856
  0x56341278

 読み出すアドレスが移動しても,最初の4バイトだけがグルグルと回って読めるようです.

 x86やARMとはエンディアンが違うPowerPCではどうでしょう.

  $ ./unaligned-powerpc
  0x12345678
  0x3456789A
  0x56789ABC
  0x789ABCDE

 エンディアンの違いはありますが,意図した値になっているようです.

 次は,PowerPCと同じビッグ・エンディアンのMicroBlazeです.

  endian   # ./unaligned-microblaze
  0x12345678
  0x12345678
  0x12345678
  0x12345678

 最初の4バイトだけ読める点はArmadillo-9と同じですが,まったく同じ値として読めるようです.

Copyright 2008 CQ Publishing Co.,Ltd.


Webmaster@kumikomi.net