第 2 章「64 ビットの使用方法」で説明したように、ほとんどの 32 ビットアプリケーションは、変更しなくても 64 ビット Solaris 環境で動作します。アプリケーションによっては、64 ビットアプリケーションとして再コンパイルしたり、完全 64 ビットプログラムに変換する必要があります。この章では、アプリケーションを再コンパイルしたり、64 ビットに変換する必要がある開発者向けに、第 2 章「64 ビットの使用方法」で述べた項目に基づいて説明します。
64 ビットオペレーティング環境でサポートされている 32 ビットアプリケーションプログラミングインタフェース (API) は、32 ビットオペレーティング環境でサポートされている API と同じです。したがって、32 ビットアプリケーションを 32 ビットおよび 64 ビットの環境間で変更する必要はありません。ただし、64 ビットアプリケーションとして再コンパイルする場合には修正作業が必要になります。64 ビットアプリケーション用にコードを修正するためのガイドラインについては、第 4 章「アプリケーションの変換」を参照してください。
64 ビット API とは、基本的に UNIX 98 ファミリーの API です。その仕様は、派生型を使って書かれています。64 ビットバージョンを作成するには、その派生型のいくつかを 64 ビットに拡張します。これらの API を使って正しく書かれたアプリケーションは、32 ビットと 64 ビット間でソースを移植できます。
SPARCTM V8 ABI は、既存のプロセッサ固有のアプリケーションバイナリインタフェース (ABI) で、32 ビット SPARC バージョンの Solaris 実装はこのインタフェースに基づいています。 SPARC V9 ABI は、 SPARC V8 ABI を拡張して 64 ビット動作をサポートし、拡張アーキテクチャの新しい機能を定義しています。追加情報については、「アプリケーションに関する新しい情報」を参照してください。
32 ビットおよび 64 ビットアプリケーション間のさまざまなレベルの互換性について説明します。
既存の 32 ビット SPARC アプリケーションは、バイナリの互換性があり、32 ビットまたは 64 ビットのオペレーティングシステム環境で実行できます。唯一の例外は、 libkvm、/dev/kmem、または /proc を使用するアプリケーションです。詳細は、第 2 章「64 ビットの使用方法」を参照してください。
32 ビットアプリケーションに対しては、ソースレベルの互換性が維持されています。64 ビットアプリケーションについては、アプリケーションプログラミングインタフェースに使用される派生型に変更が加えられています。正しい派生型およびインタフェースを使用しているアプリケーションは、32 ビットに対してソースレベルで互換性があり、より容易に 64 ビットに移行することができます。
32 ビットデバイスドライバは、64 ビットオペレーティングシステムでは使用できないため、32 ビットデバイスドライバは、64 ビットオブジェクトとして再コンパイルしなければなりません。さらに、64 ビットドライバは、32 ビットと 64 ビットの両方のアプリケーションをサポートしなければなりません。64 ビットオペレーティングシステム環境に提供されているドライバはすべて、32 ビットと 64 ビットの両方のアプリケーションをサポートしています。ただし、基本ドライバモデル、つまり DDI (Device Driver Interface) でサポートされているインタフェースに変更はありません。必要な作業は、LP64 データ型モデルの環境で適切となるようにコードを修正することです。詳細は、『Writing Device Drivers』を参照してください。
Solaris は、2 つの first class アプリケーションバイナリインタフェース (ABI) を同時にサポートしています。言い換えれば、2 つの独立した、完全に機能するシステムコールパスが、64 ビットカーネルに接続されており、2 組のライブラリがアプリケーションをサポートします。図 2-1 を参照してください。
64 ビットオペレーティングシステムは、64 ビット CPU ハードウェア上でのみ動作しますが、32 ビットオペレーティングシステムは、32 ビットと 64 ビットのどちらの CPU ハードウェア上でも動作します。32 ビット Solaris と 64 ビット Solaris の環境は同じように見えるので、特定のハードウェアプラットフォーム上でどちらのバージョンが動作しているかをすぐには判断できません。isainfo(1) コマンドを使用すると、これを簡単に確認することができます。この新しいコマンドは、システムでサポートされているアプリケーション環境に関する情報を出力します。
次に示すのは、64 ビットオペレーティングシステムが実行されている UltraSPARCTM システムで実行した isainfo(1) コマンドの出力例です。
% isainfo -v 64-bit sparcv9 applications 32-bit sparc applications |
同じコマンドを古い SPARC システム、または 32 ビットオペレーティングシステムが実行されている UltraSPARC システム上で実行した場合は、次のように出力されます。
% isainfo -v 32-bit sparc applications |
同じコマンドを x86 システム上で実行すると次のようになります。
% isainfo -v 32-bit i386 applications |
isainfo(1) コマンドのオプションの 1 つに -n オプションがあります。このオプションは、動作中のプラットフォームにネイティブな命令セットの名前を出力します。
% isainfo -n sparcv9 |
対応するネイティブのアプリケーション環境のアドレス空間のビット幅は、次のようにして確認できます。
% echo "Welcome to "`isainfo -b`"-bit Solaris" Welcome to 64-bit Solaris |
uname -r で OS のバージョンを調べるか、または /usr/bin/isainfo が存在するかどうかを調べて、64 ビット機能があるかどうかを判定することによって、以前のバージョンの Solaris で実行しなければならないアプリケーションであるかどうかを判断することができます。
関連コマンドの isalist(1) は、シェルスクリプトに使用するのに適しており、プラットフォームでサポートされている命令セットをすべて出力するのに使うことができます。isalist(1) で出力される命令セットアーキテクチャのなかには、かなりプラットフォームに固有なものもありますが、isainfo(1) ではシステム上で最も移植性のあるアプリケーション環境の属性だけを出力します。これら 2 つのコマンドとも、 sysinfo(2) システムコールの SI_ISALIST サブオプションを使って構築されています。詳細は isalist(1) のマニュアルページを参照してください。
次の例は、64 ビットオペレーティングシステムが動作している UltraSPARC システム上で isalist(1) コマンドを実行したときの出力です。
% isalist sparcv9+vis sparcv9 sparcv8plus+vis sparcv8plus sparcv8 sparcv8-fsmuld sparcv7 sparc |
サポートされる命令セットのリストは、パフォーマンスおよび機能のレベル順にソートされて出力されます。このコマンドの使用法についての詳細は、isalist(1) のマニュアルページを参照してください。また、optisa(1) のマニュアルページも参照してください。
上記の isalist(1) コマンドの出力例中にある sparcv9+vis および sparcv8+vis は、システムが UltraSPARC-1 拡張命令セットをサポートしていることを示しています。この拡張命令セットはすべての SPARC V9 システムでサポートされているわけではないので、移植できるアプリケーションはこの拡張命令セットに依存しないようにしてください。また、UltraSPARC に固有の機能に合わせてコーディングしないようにしてください。
次に示すプログラミング例では、LP64 と ILP32 のデータ型モデルの効果を直接的に示しています。同じプログラムを 32 ビットまたは 64 ビットプログラムとしてコンパイルすることができます。
デフォルトのコンパイル環境は、移植性が維持されるように 32 ビットアプリケーションを作成するように設定されています。
% cat foo.c #include <stdio.h> int main(int argc, char *argv[]) { (void) printf("char is ¥t¥t%lu bytes¥n", sizeof (char)); (void) printf("short is ¥t%lu bytes¥n", sizeof (short)); (void) printf("int is ¥t¥t%lu bytes¥n", sizeof (int)); (void) printf("long is ¥t¥t%lu bytes¥n", sizeof (long)); (void) printf("long long is ¥t¥t%lu bytes¥n", sizeof (long long)); (void) printf("pointer is ¥t%lu bytes¥n", sizeof (void *)); return (0); } |
32 ビットコンパイルの例
% cc -O -o foo32 foo.c % foo32 char is 1 bytes short is 2 bytes int is 4 bytes long is 4 bytes long long is 8 bytes pointer is 4 bytes |
64 ビットコンパイルの例
% cc -xarch=v9 -O -o foo64 foo.c % foo64 char is 1 bytes short is 2 bytes int is 4 bytes long is 8 bytes long long is 8 bytes pointer is 8 bytes |