Solarisのディレクトリ構成

Solarisのディレクトリ構成
ディレクトリ説明
/cdromCD-ROMドライブ用マウントポイント
/devデバイスファイル
/etc設定ファイル
/exportNFS共有ディレクトリ
/home/export/homeのマウントポイント
/kernelカーネルなど
/lib共有ライブラリ
/mnt一時的なマウントポイント
/netオートマウント用マウントポイント
/optアプリケーションインストール用
/platformアーキテクチャに依存するプログラム
/procプロセスファイルシステム
/sbinシステム管理用コマンド
/tmp一時的なファイル
/usr各種プログラム
/var変更されるデータ

Solaris インストールパッケージ

Solaris の pkgadd 形式のキットは次の4階層から構成されます。

  1. ボリューム
  2. インスタンス
  3. クラス
  4. オブジェクト
ボリューム
MT、ファイル、ディレクトリなど、キットそのものである。
インスタンス
インスタンスはボリュームに複数存在し、インストールの単位になる。
クラス
クラスは、インスタンスの中に複数存在する。オブジェクトをグループに分ける。キットの中で特定のグループをインストールしたり、しないようにしたり変更できる。
オブジェクト
実際のファイルやディレクトリ

パッケージのまとめ方

pkgtransコマンドは、ボリュームに含まれるインスタンスを別のボリュームにコピーする。 ボリュームVOL1にインスタンスINS1、INS2、INS3が入っている場合、

$ pkgtrans VOL1 VOL2 INS1 INS2

VOL2にはインスタンスINS1、INS2が作成される。

MTやファイルがボリュームの場合、pkgtransを使うと、ボリュームの先頭からインスタンスが複写される。 このため、VOL2に別のインスタンスがあっても、これは消えてしまう。このため、複数のボリュームからインスタンスを 集めることはできない。

ボリュームVOL1にインスタンスINS1が入っていて、ボリュームVOL2にインスタンスINS2が入っている場合

$ pkgtrans VOL1 VOL3 INS1
$ pkgtrans VOL2 VOL3 INS2

VOL3にはインスタンスINS2しか残らない。

ボリュームには、もうひとつディレクトリを指定することができる。ディレクトリの場合、MTやファイルと違って、追加のコピーをすることができる。

ボリュームVOL1にインスタンスINS1が入っていて、ボリュームVOL2にインスタンスINS2が入っている場合

$ mkdir VOL3
$ pkgtrans VOL1 VOL3 INS1
$ pkgtrans VOL2 VOL3 INS2

VOL3にはインスタンスINS1とINS2が入る。

ディレクトリに作成したインスタンスを改めてファイルやMTにpkgtransすれば、MTやファイルに複数のインスタンスのキットを 作成できる。ディレクトリを仲介することで、インスタンスを自由にまとめたり、分離できる。インストールの場合、 上記のボリュームVOL3を使うと、次のようになる。

$ pkgadd -d VOL3 INS1 INS2
$ pkgadd -d VOL3 INS2
$ pkgadd -d VOL3

ホームディレクトリをオートマウントする

このドキュメントでは、ホームディレクトリの実体がどのパーティションにあっても、/home としてアクセスできるようにするための手順を説明します。

df コマンドで /home を調べると、ファイルシステムが auto_home になっています。

# df -k /home
ファイルシステム      kbytes 使用済み 使用可能 capacity  マウント先
auto_home                  0       0       0     0%    /home
#

これは、/export/home 等にあるディレクトリをオートマウントすることによって、 ホームディレクトリの実体がどのパーティションにあっても、/home としてアクセスできるようにするためです。 ハードディスクを増設して /export/home2、/export/home3、・・・ とディレクトリが変わっても、すべて /home としてアクセスできます。 ただし、/home としてアクセスできるようにするためには、手続きが必要です。

/etc/dfs/dfstab の設定

自動マウント・デーモン (automountd) がマウントする対象ディレクトリ (/export/home) を共有化されていなければなりません。 共有化されているかどうかは、share コマンドで確認することができます。

# share
-               /export/home   rw   ""
#

もし /export/home に関して何も表示されなければ共有化されていません。

automountd が自動的に対象ディレクトリを共有化するためには、/etc/dfs/dfstab を編集して、以下の行を追加します。

share -F nfs /export/home

これで、コンピュータを起動したときに automountd が自動的に対象ディレクトリを共有化するようになります。

/etc/auto_home の設定

/etc/auto_home に /export/home/username を /home/username に自動的にマウントするように記述します。このマシンのホスト名は myhost とします。

username myhost:/export/home/username

/etc/nsswitch.conf の設定

/etc/auto_home の中に記述したホスト名は、何をもって解決するか定義します。 /etc/nsswitch.conf というファイルに、以下の行が記述されていることを確認します。

automount: files

/etc/auto_master の設定

/etc/auto_master というファイルに、以下の行が記述されていることを確認します。

/home auto_home -nobrowse

自動マウント・デーモンの再起動

各ファイルの設定が終わったら、自動マウント・デーモン (/usr/lib/autofs/automountd) を再起動します。

# /etc/init.d/autofs stop
# /etc/init.d/autofs start

Solaris 10以降の場合は、 svcadm(1M) コマンドを使用する。

# svcadm disable system/filesystem/autofs
# svcadm enable system/filesystem/autofs

ログイン

これでホームディレクトリのオートマウントの手続きは完了しました。ログインすると、ホームディレクトリが /home/username になっています。

login: username
Password:
Last login: Wed Apr 19 10:08:09
Sun Microsystems Inc.   SunOS 5.8       Generic Patch   February 2004
% pwd
/home/username

CD-ROMのマウント

CD-ROMは、ボリューム・デーモン (vold) が自動的にマウント/アンマウントを行います。次に vold デーモンの起動方法を示します。

# /etc/init.d/volmgt start

CD-Rを装置から取り出すときには eject コマンドを使用します。このとき自動的にアンマウントされます。

# eject cdrom

次に vold デーモンの停止方法を示します。

# /etc/init.d/volmgt stop

手動でマウントする場合は、mount コマンドを使用します。次に、マウント元 /dev/dsk/c0t6d0s2、マウント先 /mnt の場合のコマンド実行例を示します。

# mount /dev/dsk/c0t6d0s2 /mnt

CD-ROM ドライブをマウントすると、CD-ROM が使えるようになります。

CD-ROM ドライブに挿入している CD-ROM メディアを取り出すには eject コマンドを使用します。

% eject cdrom

NFS

NFS (Network File System)は、OSに依存しないネットワーク透過なファイルシステムである。

リモートコンピュータのCD-ROMをマウントする

example1 から example2 の CD-ROM をマウントするには、まず example2 でルートユーザが CD-ROM ドライブを共有します。

example2# share /cdrom /cdrom

共有状態は share コマンドで確認することができます。

一方、example1 ではルートユーザで CD-ROM ドライブを NFS マウントします。ここでは、exmaple2 のIPアドレスを 201.101.51.82 とします。

mount -F nfs 201.101.51.82:/cdrom/cdrom /cdrom

これで、リモートコンピュータの CD-ROM ドライブを使用できるようになりました。

mountd デーモンや nfsd デーモンが存在しないとエラーになります。この場合は mountd や nfsd デーモンを起動してください。

example1# /usr/lib/nfs/mountd
example1# /usr/lib/nfs/nfsd -a 16

リモートコンピュータの CD-ROM を使用しなくなったら、アンマウントします。

example1% umount /cdrom

リモートコンピュータでは共有を解除します。

example2% unshare /cdrom/cdrom

カーネル・パラメータのチューニング

システム定義を出力するには sysdef コマンドを使用します。

$ sysdef | grep SHMMAX
   1048576      max shared memory segment size (SHMMAX)

/etc/systemファイルは、Solarisのチューニングなどでさまざまなオプションを指定することができます。

/etc/systemファイルの書式は次の通りです。

set variable = 

variable には変数名を指定します。次に変数の一覧を示します。

メッセージキュー
変数名 パラメータ 意味
msgsys:msginfo_msgmax MSGMAX System V メッセージの最大サイズ
msgsys:msginfo_msgmnb MSGMNB 1つのメッセージキューに入れることができるバイト数の最大値
msgsys:msginfo_msgmni MSGMNI 作成することができるメッセージキューの最大数
msgsys:msginfo_msgtql MSGTQL 作成できるメッセージの最大数
セマフォ
変数名 パラメータ 意味
semsys:seminfo_semmni SEMMNI セマフォ識別子の数
semsys:seminfo_semmns SEMMNS システム内のセマフォ数
semsys:seminfo_semmnu SEMMNU 取り消し機能を使うプロセスの数
semsys:seminfo_semmsl SEMMSL 1つのIDに対する最大セマフォ数
共有メモリ
変数名 パラメータ 意味
shmsys:shminfo_shmmax SHMMAX 共有メモリ領域の最大サイズ(バイト単位)
shmsys:shminfo_shmmin SHMMIN 共有メモリ領域の最小サイズ(バイト単位)
shmsys:shminfo_shmni SHMMNI システム全体での共有メモリ領域の最大個数
shmsys:shminfo_shmseg SHMSEG プロセスあたりの共有メモリ領域の最大個数

セマフォ識別子の数を20に設定するには、/etc/systemに次の文を記述します。

set semsys:seminfo_semmni = 20

/etc/systemファイルを変更したら、設定の変更を有効にするためにシステムのリブートが必要です。

Solaris資源制御

カーネル・パラメータの変更には、システムのリブート(再起動)が必要なうえ、すべてのユーザーに影響が及ぶ。

Solaris 10から資源制御(リソース・コントロール)が導入され、プロジェクトまたはプロセス、タスクごとにリソースを制御できるようになった。また、リソースの種類によっては、システムを再起動することなく動的に変更することができる。

資源の制御を行なうには、 prctl(1) コマンドを使用する。

prctl [-t [basic|privileged|system]] [-e|-d	action] [-rx] [-n name [-v value]] [-i	idtype] [id	...]
-i idtype
IDオペランドのタイプを指定する。
IDタイプ
IDタイプ
process
project
task
-n name
getまたはsetする資源制御の名前を指定する。 -n オプションを省略した場合、全ての資源制御が対象となる。
資源制御の名前
名前 説明
project.max-sem-ids セマフォ識別子の数
process.max-sem-nsems 1つのIDに対する最大セマフォ数
project.max-shm-memory 共有メモリ領域の最大サイズ(バイト単位)
project.max-shm-ids システム全体での共有メモリ領域の最大個数
-r
最初の資源制御値を新しい値( -v オプションで指定する)で置き換える。
-v value
set操作の資源制御値を指定する。 value が指定されなかった場合、変更は最小値となる。
id
エンティティ(processまたはtask、project)の識別子。 -i オプションを指定していない場合、プロセスIDを指定する。 -i オプションに project を指定した場合、 id にはプロジェクトIDを指定する。

現在のプロセスの最大セマフォ数を表示する例を示す。

% prctl -n process.max-sem-nsems $$
process: 393: -csh
NAME    PRIVILEGE     VALUE FLAG ACTION RECIPIENT
process.max-sem-nsems
        privileged    1.02K    -   deny         -
        system        32.8K  max   deny         -

現在のプロセスの共有メモリ最大サイズを表示する例を示す。

$ prctl -n project.max-shm-memory $$

$$ は、現在のプロセスのプロセスIDを表すシェル変数である。

defaultプロジェクトの共有メモリ最大サイズを表示する例を示す。

$ prctl -n project.max-shm-memory -i project default

-i オプションにprojectを指定したので、 id にはプロセスIDではなくプロジェクトIDを指定している。

defaultプロジェクトの共有メモリ最大サイズを4Gバイトに設定する例を示す。

$ prctl -n project.max-shm-memory -v 4gb -r -i project default

defaultプロジェクトの共有メモリ最大個数を100に設定する例を示す。

$ prctl -n project.max-shm-ids -v 100 -r -i project default

プロジェクト

Solaris 10ではシステムにログインする際、任意のプロジェクトが割り当てられます。プロジェクトで指定されたユーザーリストやグループリストに含まれていない場合でも、自動的にそのデフォルトプロジェクトのメンバーになります。

ユーザーがどのプロジェクトに割り当てられているかを確認するには、 id -p コマンドを使用します。

$ id -p
uid=108(yamada) gid=102(sales) projid=3(default)

useradd コマンドで新しいログイン・ユーザーを作成する際、ユーザーに関連付けるプロジェクトを -p オプションで指定することができる。

# useradd -p hello yajima

useradd コマンドで-pオプションを指定しなかった場合、デフォルトでdefaultというプロジェクトが割り当てられる。

システムに新しいプロジェクトを作成するには、 projadd(1M) コマンドを使用する。

projadd [-c comment] [-U user [,user...]] [-G group[,gourp... ]] [-p projid [projid... ]]	project

Solarisパッチのインストール

Solarisのパッチは http://sunsolve.sun.com から入手することができる。

現在適用されているパッチを確認するには showrev -p を実行する。

% showrev -p | more
Patch: 110378-06 Obsoletes: 110198-01, 110550-01 Requires: 109279-09, 109472-05,
 109740-04, 109742-03 Incompatibles:  Packages: SUNWmipr, SUNWmipu
(中略)
Patch: 125136-12 Obsoletes:  Requires:  Incompatibles:  Packages: SUNWj6rt, SUNW
j6dev, SUNWj6cfg, SUNWj6man, SUNWj6dmo
%

dbx デバッガー

子プロセスのデバッグ

子プロセスが新しいプログラムをexec関数を用いて実行すると、そのプロセスIDは変わりませんが、プロセスイメージは変化します。 dbxはexec関数の呼び出しを自動的に検知し、新しく実行されたプログラムを自動的に再読み込みします。 実行可能ファイルの元の名前は $oprog に保存されます。この名前に復帰するには debug $oprog コマンドを使用します。

子プロセスが関数 fork、vfork を呼び出すとプロセスIDが変化しますが、プロセスイメージは変化しません。 dbxenv 環境変数 follow_for_mode の設定値にしたがって dbx は次のように動作します。

設定値 動作
parent dbxは親プロセスを追跡します。
child dbxは新しいプロセスIDで分岐先の子プロセスに自動的に切り替わります。
both このモードはSun WorkShopからdbxを使用する場合しか利用できません。
ask dbxがforkを検出するたびにプロンプトが表示され、parent、child、bothのどのモードを使用するか問い合わせてきます。

watchmalloc

アプリケーションがヒープ領域を破壊している可能性が考えられる場合、watchmallocという機能で確認することができます。

使い方は、環境変数を設定してからアプリケーションを実行します。

$ LD_PRELOAD=watchmalloc.so.1

free()から戻る前に、メモリの解放されたブロックはパターン0xdeadbeefで上書きされます。

前回のfree()から内容が変更されていないメモリを受け取ると誤認しているアプリケーションに対する予防措置として、malloc()は確保したメモリをパターン0xbaddcafeで満たして返します。

calloc()は常に0で満たされたメモリを返します。

さらに、ウォッチポイント機能を有効にするには、変数 MALLOC_DEBUG を設定します。

$ MALLOC_DEBUG=WATCH

ただし、ウォッチポイント機能を有効にすると、実行速度が10倍から100倍くらい遅くなります。

アプリケーションが解放済みのメモリに書き込もうとすると、それがウォッチポイントトラップのトリガー(引き金)となり、SIGTRAPシグナルが発生します。通常、SIGTRAPシグナルが発生すると、アプリケーションはcoreを作成して終了します。

環境変数MALLOC_DEBUGには、カンマで区切ってさらにオプションを指定することができます。

$ MALLOC_DEBUG=WATCH,RW,STOP
RW
解放済みメモリに書き込もうとしたときだけでなく、読み出そうとしたときにもウォッチポイントトラップのトリガーとなります。このオプションを指定すると、アプリケーションの実行速度が1,000倍くらい遅くなります。

ロケール

ロケールは、言語固有の書式やその他の仕様による、いくつかのカテゴリで構成されています。 プログラムのロケールは、コードセットや、日付および時間の表記規則、通貨の表記規則、小数の表記規則、照合の順序などを決定します。 通常、ロケール名は環境変数 LANG で指定します。 ロケールのカテゴリは LANG に依存しますが、別に設定することも可能です。 この場合、ロケールのカテゴリは LANG の設定に優先します。 LC_ALL が設定されている場合、LC_ALL の設定は LANG だけでなく、ロケールの個別のカテゴリに優先されます。

高い <---------- 優先順位 ---------> 低い
カテゴリ 第 1 の環境変数 第 2 の環境変数 第 3 の環境変数
LC_CTYPE LC_ALL LC_CTYPE LANG
LC_COLLATE LC_ALL LC_COLLATE LANG
LC_TIME LC_ALL LC_TIME LANG
LC_NUMERIC LC_ALL LC_NUMERIC LANG
LC_MONETARY LC_ALL LC_MONETARY LANG
LC_MESSAGES LC_ALL LC_MESSAGES LANG

ロケールのカテゴリ

LC_CTYPE
文字処理関数の動作を制御するカテゴリ。
LC_TIME
日付と時間の形式を指定する。指定には月の名前、曜日、一般的な完全表記と省略表記も含まれる。
LC_MONETARY
通貨形式を指定する。SunOSのコマンドやライブラリルーチンで実際にこのカテゴリを使用するものはほとんどない。
LC_NUMERIC
10進数区切り子(小数点文字)および千単位の区切り文字を指定する。
LC_COLLATE
ロケールのソート順序や、この順序を実現するために必要な文字列の変換方式を指定する。
LC_MESSAGE
言語対応されたメッセージの言語を指定する。

ロケール名

ja
日本語EUCに基づいたロケール。
ja_JP.eucJP
日本語EUCに基づいたロケール。
ja_JP.PCK
Shift_JISとして知られる PC-Kanji コードに基づいたロケール。
ja_JP.UTF-8
UTF-8に基づいたロケール。

プログラミングの国際化

国際化はソフトウェアを任意のロケールに依存しないようにする処理です。 国際化したソフトウェアは特定のロケールに容易に適用させることができます。

国際化の基本的な手順

再コンパイルしなくても異なる環境に動的に対応できるソフトウェアを作成します。 ソフトウェアを実行可能イメージとメッセージに分離します。メッセージには、操作中に印刷または表示 されるすべてのメッセージが含まれます。メッセージ文字列はメッセージデータベースに格納します。

システムライブラリを動的にリンクする

アプリケーションを libc などのシステムライブラリにリンクする方法として、動的リンクと静的リンクを選択できます。 しかし、システムライブラリの国際化機能を必要とするアプリケーションは動的にリンクしなければなりません。 つまり、libc.a ではなく libc.so とリンクしなければなりません。

setlocale() を呼び出して LC_CTYPE カテゴリを設定する

SunOS システムは、POSIX/ANSI C の setlocale() という関数をサポートします。 この関数は、言語や文化的慣習を初期設定するものです。 ディスクやネットワークに対するブロック入出力のような文字の解釈を行わないアプリケーションを除いて、ほとんどのアプリケーションはロケールの LC_CTYPE カテゴリを設定しなければなりません。 ひとつのアプリケーションで複数のコードセットを動的に制御するには、以下の行をコードに追加します。

#include <locale.h>

main() {
    (void) setlocale(LC_CTYPE, "");
}

setlocale() の呼び出せないアプリケーションは、国際化機能を使用できません。 上記のロケールのすべてのカテゴリを同時に設定するときには、setlocale の引数として LC_CTYPE ではなく LC_ALL を使用します。 実際には、ほとんどのアプリケーションが、LC_ALL カテゴリを一度だけ設定することになるはずです。

形式

世界中には、日付や時間、通貨、数、単位を表現するためのさまざまな形式がある。たとえば、日本では日付を表す形式として年月日の順で表すのが一般的である。しかし、アメリカでは月日年、イギリスでは日月年の順で表すのが一般的である。これらの形式をプログラムコードに直接組み込んではならない。プログラムでは、setlocale() を呼び出し、その後で各種のロケールに固有な形式のルーチンを呼び出すようにして、形式の設定そのものは国や言語ごとの各国語対応作業に委ねるようにする。

時間と日付の形式

多くのロケールで有効な時間と日付の形式を作成するには、 strftime() ライブラリルーチンを使用します。まず、 time() を呼び出してプログラムのクロックを設定し、次に localtime() を呼び出して tm 構造体を生成します。この構造体に日付と時間の形式とデータ保持用のバッファを加えて strftime() に渡します。

#include <locale.h>
#include <stdio.h>
#include <time.h>
main() {
    time_t clock, time();
    struct tm *tm, *localtime();
    char buf[128];

    setlocale(LC_ALL, "");
    clock = time((time_t *)0);
    tm = localtime(&clock);
    strftime(buf, sizeof(buf), "%c", tm);
    printf("%s\n", buf);
}

日付と時刻を各国固有の短い形式で表すには %c を、長い形式であらわすには %C を使用します。 また、 %x を使用すると各国固有の日付の形式が数字で表現され、 %X では時間の形式が生成されます。

strcmp() から strcoll() への置き換え

strcmp() は ASCII の順序で照合を行うので、英語の場合でも a は Z の後になります。この順序が適切で ない場合もあります。一方、新しいライブラリルーチンの strcoll() と strxfrm() では、任意のソート 順序を作成できます。strcoll() は文字列の比較に使用し、strxfrm() は正しく照合できる文字列に変換 するために使用します。

catgets() を使用したメッセージ処理

テキスト処理を国際化および各国語対応する手順は次のとおりです。

  1. ソースコードを変更して #include <nl_types.h> を追加し、catopen() を呼び出してカタログから文字列を取り出す。
  2. catgets() 呼び出しから元の言語のテキスト文字列を抽出し、ソースメッセージカタログに保存する。 各くメッセージに固有の番号を割り当て、その番号はソースカタログと、メッセージを参照する catgets() 呼び出しの両方に表示されるようにしなければならない。
  3. ソースメッセージカタログの文字列を対象とする言語に翻訳する。
  4. gencat(1) ユーティリティを使用して、翻訳されたソースメッセージカタログをバイナリメッセージ カタログに変換する。バイナリカタログをインストールする。

メッセージカタログの検索

catopen() 関数は以下の規則に従ってメッセージカタログを検索します。

#include <locale.h>
#include <nl_types.h>
nl_catd catd;
main() {
    (void) setlocale(LC_ALL, "");
    catd = catopen("demo", NL_CAT_LOCALE);
}
  1. 使用されるロケールは、setlocale() により設定された LC_MESSAGSE の値である。catopen() の 2番目の引数として使用できるのはこの他に0だけで、この場合使用されるロケールは、環境変数 LANG の値である。
  2. 環境変数 NLSPATH の最初の引数を使用して、カタログが検索される。

NLSPATH 変数は、次のようにコロンで区切られたファイル名のリストです。

/usr/lib/locale/%L/LC_MESSAGES/%N.cat:/tmp/%N.%L.cat

このようなパターンにおいて、 catopen() %N を最初の引数("demo")に置き換え、%L を判明した ロケールに置き換えます。たとえば、ロケールが日本語に設定されている場合は、catopen() は /usr/lib/locale/ja/LC_MESSAGES/demo.cat というファイルを使用します。これに失敗すると、 /tmp/demo.ja.cat というファイルを使用します。

ソースメッセージカタログの作成

genmsg ユーティリティは、国際化されたソースメッセージカタログを作成するために catgets() ファミリの関数で使用されます。このユーティリティは、ソースプログラムファイルの catgets での 関数呼び出しを調べ、見つかった情報からソースメッセージカタログを作成します。 以下に例を示します。

% cat example.c
...
    /* NOTE: %s is a file name */
    printf(catgets(catd, 5, 1, "%s cannot be opend."), fname);
    /* NOTE: "Read" is a past participle, not a present tense verb */
    printf(catgets(catd, 5, 2, "Read"));
...
% genmsg -c NOTE exsample.c
The following file(s) have been created.
    new msg file = "example.c.msg"
% cat example.c.msg
$quote "
$set 5
1    "%s cannot be opend"
    /* NOTE: %s is a file name */
2    "Read"
    /* NOTE: "Read" is a past participle, not a present tense verb */

バイナリメッセージカタログの作成

翻訳された各ソースカタログについてバイナリメッセージカタログを作成します。バイナリカタログは アプリケーションが実行時に参照するカタログです。getcat ユーティリティを使用してバイナリ カタログファイルを生成します。日本語のソースメッセージカタログが demo.ja.msg という 名前である場合、次のように入力します。

% cat demo.ja.msg
$quote "
$set 5
1    "%s がオープンできません"
    /* NOTE: %s is a file name */
2    "読み込み"
    /* NOTE: "Read" is a past participle, not a present tense verb */
% gencat demo.ja.cat demo.ja.msg

バイナリカタログが正常に作成されたら、最終的な場所(/usr/lib/locale/ko/LC_MESSAGES/demo.cat) にインストールします。

まとめ

アプリケーションのテキスト処理を国際化して各国語対応するには、以下の手順に従います。

  1. ロケールを設定した後、メッセージカタログを開く。
  2. catgets() を呼び出して、カタログから文字列を取り出す。
  3. ソースメッセージカタログから元の言語のテキスト文字列を抽出する。翻訳が困難な文字列には コメントをつける。
  4. ソースメッセージカタログ内の文字列を目的の言語に翻訳する。
  5. 翻訳された各ソースメッセージカタログをバイナリメッセージカタログに変換する。
  6. アプリケーションをインストールする際に、バイナリメッセージカタログをインストールする。

64ビットプログラミング

32ビットアプリケーションは int、long およびポインタが32ビットである ILP32 データ型モデルに基づいているのに対し、 64ビットアプリケーションは long およびポインタが64ビットである LP64 データ型モデルに基づいています。

Solaris が32ビットまたは64ビット環境のどちらで動作しているかを調べるには、isainfo コマンドを使用します。

% isainfo -v
64-bit sparcv9 applications

64ビットアプリケーションは64ビットカーネル上で動作します。32ビットアプリケーションは32カーネルおよび64ビットカーネルのどちらでも動作します。

アプリケーションを64ビットでコンパイルするには、cc コマンドに -xarch=v9 (または -xarch=generic64 )オプションを指定します。

% cc -xarch=generic64 foo.c

64ビットのオブジェクトファイルは、64ビットのオブジェクトおよびライブラリーとリンクすることができます。32ビットのオブジェクトやライブラリーとはリンクできません。

リンカーに ld を使用する場合は、とくにオプションを指定する必要はありません。コマンド行から処理される最初のオブジェクトファイルが64ビットオブジェクトであれば自動的に判定されます。

ソケットやシグナル等の IPC を使用して 64ビットのアプリケーションと32ビットのアプリケーションがプロセス間通信を行うことは可能です。

LP64 データ型モデルでは、long およびポインタが64ビットに変更されました。

データ型サイズ(単位:ビット)
Cデータ型 ILP32 LP64
char 8 変更なし
short 16 変更なし
int 32 変更なし
long 32 64
long long 64 変更なし
ポインタ 32 64
enum 32 変更なし
float 32 変更なし
double 64 変更なし
long double 128 変更なし

また、<sys/types.h> ヘッダーに含まれる派生型の中にも64ビットに拡張されているものがあります。

データ型サイズ(単位:ビット)
派生型 ILP32 LP64 備考
clock_t 32 64 システム時間(クロック刻み)
dev_t 32 64 デバイス番号
off_t 32 64 ファイルサイズとオフセット
pid_t 32 変更なし プロセスID
ptrdiff_t 32 64 2つのポインタの減算結果を示す符号付き整数型
size_t 32 64 符号なしサイズ
ssize_t 32 64 符号付きサイズ
time_t 32 64 秒単位の時間
uid_t 32 変更なし ユーザー識別子

アドレス計算をする際は、ヘッダファイル <inttypes.h> をインクルードして intptr_tuint_ptr_t 型を使用します。 これらはポインタを格納するために十分なサイズの符号付き整数型および符号なし整数型です。

32ビット用と64ビット用で明示的にソースコードを分ける場合には、 _LP64 または _ILP32 というマクロを使用します。

#ifdef _LP64
/* 64ビット用 */
#endif

#ifdef _ILP32
/* 32ビット用 */
#endif

lint コマンドで 64ビット関連の問題について警告を表示させるには -Xarch=v9 および -errchk=longptr64 オプションを指定します。

32ビット環境では32ビットのアプリケーションを実行して、64ビット環境では64ビットのアプリケーションを実行したい場合、ラッパーを使います。 /usr/lib/isaexec コマンドがこのラッパー機能を持っています。

例えば、/usr/lib/isaexec をハードリンクするかコピーして /home/user/foo というファイルを作成します。 32ビットアプリケーションを /home/user/sparcv7/foo に、64ビットアプリケーションを /home/user/sparcv9/foo に配置します。 こうすることで、/home/user/foo を実行すればラッパーが自動的に起動するアプリケーションを判定します。

スポンサーリンク