VA Linux Systems Japan株式会社

VA Linux 採用情報
ホーム 検索 お問い合わせ

English

サービス・製品

技術情報・資料

オープンソースプロジェクト イベント情報

出版・執筆

プレスリリース

会社情報

採用情報

 
 

 

ホーム VA Tech.Top テックライブラリーTop Linuxと64bit環境 1.3

update : 2007/10/15

 

index

Xen特集

テックライブラリ

Linuxと64bit環境

 

第1章

64bit環境の概要

1.1

64bitプロセサ

1.2

64bitメモリ環境

1.3

LP64プログラミング環境

1.4

AMD64命令セット/Intel 64拡張

第2章

Linuxの64bit対応の動向

2.1

AMD64/Intel 64以前の64bit対応

2.2

AMD64/Intel 64への対応

2.3

各ディストリビューションの対応状況

第3章

アプリケーションプログラムの64bit移行に際して

3.1

一般的な注意事項1

3.2

一般的な注意事項2

3.3

一般的な注意事項3

3.4

一般的な注意事項4

3.5

移行のためのヒント

参考

関連図書

プレゼンライブラリ

イベントレポート

tips

VA Virtual-suite

仮想化に関するレポート販売

Xenを使ってみよう

Kernel対応障害解析サービス VA Quest

   
 
 


Linuxと64bit環境

1.3 LP64プログラミング環境

 64bitプロセサのためのプログラムを、C/C++で書く際に注意すべき点の1つが、整数データモデルの違いです。

表1.2:整数データモデルの比較 32bit環境ではポインタは32bitであり、int型と同じ幅でした。64bitプロセサのプログラミング環境では、ポインタの幅が64bitとなります。Cの言語仕様(ISO/IEC 9899:1999 Programing Languages - C[5]、C99)においては、intは「実行環境のアーキテクチャの暗示する自然な大きさ」となっており、64bitプロセサにおいては64bitとなりそうではありますが、そうではない実装が主流となっています。主な整数データモデルを【表1.2】に示します。

ILP32

int、long int、ポインタが32bit、すなわち一般的な32bit環境です。long long int※1として64bit整数が提供される処理系も多くなっています。

LLP64

ポインタを除き、各整数型についてはILP32と同じデータモデルです。64bit版のWindows(Win64)ではこのデータモデルが採用されています。32bit環境で作られ、int型またはlong int 型の変数にポインタを保持するような処理をしているプログラムをLLP64環境に移植しようとすると、ポインタの上位32bitが落とされて致命的な問題が発生することがあります。ポインタを除く整数型についてはILP32と同じなので、それ以外の問題は起きにくいと考えられます。

LP64

long intを64bitとしたデータモデルです。Linuxも含めて、多くの64bit Unixではこのデータモデルが採用されています。int型変数にポインタを保持するようなプログラムでは、LLP64と同じような問題が発生しますが、long int型変数の場合には問題が顕在化しません。また、32bit環境においては、intとlong intが混用されても問題にならないことが多く※2、こうしたプログラムもLP64環境に移植した際に問題が発生します。

ILP64

intも64bitとしたデータモデルです。一部のオペレーティングシステムやコンパイラがそのような動作モードを持ちますが、LP64など他のデータモデルも用意されていることが多く、使われることは少ないようです。int型やlong int型の変数にポインタを格納しても、情報の欠落は発生せず、問題が顕在化しません。

 処理系によっては、複数のデータモデルをサポートしており、コンパイラのオプションなどで切り替えることができます。たとえば、x86-64用のLinuxで広く使われているC/C++コンパイラgccでは、-m64オプションを付けることでLP64モード、-m32オプションを付けることでILP32モードとなります。-m32オプションを付けた場合、出力されるバイナリファイルはIA-32用になります。

 C99では、整数型の幅を明示的に指定するための方法を規定しています。ヘッダファイル<stdint.h>を#includeすることで、 以下の型が適切にtypedefされます。

intN_t

ちょうどNbitの幅を持つ符号付き整数の型。一般に、N は8、16、32、64。

uintN_t

ちょうどNbitの幅を持つ符号なし整数の型。一般に、N は8、16、32、64。

intmax_t

もっとも幅の広い符号付き整数の型。

intptr_t

ポインタを保持できる符号付き整数の型。

uintptr_t

ポインタを保持できる符号なし整数の型。

int_leastN_t

最低Nbitの幅を持つ符号付き整数の型。N は8、16、32、64。

uint_leastN_t

最低Nbit の幅を持つ符号なし整数の型。N は8、16、32、64。

int_fastN_t

最低Nbitの幅を持ち、かつ最も処理が速い符号付き整数の型。N は8、16、32、64。

uint_fastN_t

最低Nbitの幅を持ち、かつ最も処理が速い符号なし整数の型。N は8、16、32、64。

#include <stdio.h>
#include <stdint.h>    /* inttypes.h 使用時は自動的に読み込まれる*/
#include <inttypes.h>
int main(void)
{
 uint8_t a = 30;
 int64_t b = 10;
 printf("a=%" PRId8 "(0x%" PRIx8 "), b=%" PRId64 "\n", a, a, b);
 return 0;
}

実行例

a=30(0x1e), b=10

【図1.1: inttypes.h、stdint.h の使用例】

 さらに、これらに対応してprintf関数などの書式文字列も定義されています。ヘッダファイル<inttypes.h>を#includeすることで、以下のマクロが適切に定義されます。

PRIdN、PRIiN

intN_tを10進数で出力する変換指定子。dまたはiに適切な長さ修飾子を付けたもの。

PRIuN

uintN_tを10進数で出力する変換指定子。uに適切な長さ修飾子を付けたもの。

PRIoN

uintN_tを8進数で出力する変換指定子。oに適切な長さ修飾子を付けたもの。

PRIxN、PRIXN

uintN_tを16進数で出力する変換指定子。xまたはXに適切な長さ修飾子を付けたもの。

 同様に、PRIdMAX、PRIdPTR、PRIdLEASTN、PRIdFASTN なども定義されます。さらに、scanf関数などのための書式文字列として、SCNdN なども定義されます。

 

※1

C99で規定されましたが、処理系によってはそれ以前からサポートされていました。

※2

典型的には、long int型の変数を、printfの書式文字列%d、%x(長さ修飾子なし)などで表示しようとするものです。

 

戻る  次へ