Solarisはオラクルが販売しているUnix系のOSです。この記事では、Solarisの使い方をサンプルを交えてご紹介します。
ディレクトリ | 説明 |
---|---|
/cdrom | CD-ROMドライブ用マウントポイント |
/dev | デバイスファイル |
/etc | 設定ファイル |
/export | NFS共有ディレクトリ |
/home | /export/homeのマウントポイント |
/kernel | カーネルなど |
/lib | 共有ライブラリ |
/mnt | 一時的なマウントポイント |
/net | オートマウント用マウントポイント |
/opt | アプリケーションインストール用 |
/platform | アーキテクチャに依存するプログラム |
/proc | プロセスファイルシステム |
/sbin | システム管理用コマンド |
/tmp | 一時的なファイル |
/usr | 各種プログラム |
/var | 変更されるデータ |
Solaris の pkgadd 形式のキットは次の4階層から構成されます。
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 としてアクセスできるようにするためには、手続きが必要です。
自動マウント・デーモン (automountd) がマウントする対象ディレクトリ (/export/home) を共有化されていなければなりません。 共有化されているかどうかは、share コマンドで確認することができます。
# share
- /export/home rw ""
#
もし /export/home に関して何も表示されなければ共有化されていません。
automountd が自動的に対象ディレクトリを共有化するためには、/etc/dfs/dfstab を編集して、以下の行を追加します。
share -F nfs /export/home
これで、コンピュータを起動したときに automountd が自動的に対象ディレクトリを共有化するようになります。
/etc/auto_home に /export/home/username を /home/username に自動的にマウントするように記述します。このマシンのホスト名は myhost とします。
username myhost:/export/home/username
/etc/auto_home の中に記述したホスト名は、何をもって解決するか定義します。 /etc/nsswitch.conf というファイルに、以下の行が記述されていることを確認します。
automount: files
/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は、ボリューム・デーモン (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 (Network File System)は、OSに依存しないネットワーク透過なファイルシステムである。
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 10から資源制御(リソース・コントロール)が導入され、プロジェクトまたはプロセス、タスクごとにリソースを制御できるようになった。また、リソースの種類によっては、システムを再起動することなく動的に変更することができる。
資源の制御を行なうには、 prctl(1) コマンドを使用する。
prctl [-t [basic|privileged|system]] [-e|-d action] [-rx] [-n name [-v value]] [-i idtype] [id ...]
IDタイプ |
---|
process |
project |
task |
名前 | 説明 |
---|---|
project.max-sem-ids | セマフォ識別子の数 |
process.max-sem-nsems | 1つのIDに対する最大セマフォ数 |
project.max-shm-memory | 共有メモリ領域の最大サイズ(バイト単位) |
project.max-shm-ids | システム全体での共有メモリ領域の最大個数 |
現在のプロセスの最大セマフォ数を表示する例を示す。
% 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
現在適用されているパッチを確認するには 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
%
子プロセスが新しいプログラムを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という機能で確認することができます。
使い方は、環境変数を設定してからアプリケーションを実行します。
$ 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
ロケールは、言語固有の書式やその他の仕様による、いくつかのカテゴリで構成されています。 プログラムのロケールは、コードセットや、日付および時間の表記規則、通貨の表記規則、小数の表記規則、照合の順序などを決定します。 通常、ロケール名は環境変数 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 |
国際化はソフトウェアを任意のロケールに依存しないようにする処理です。 国際化したソフトウェアは特定のロケールに容易に適用させることができます。
再コンパイルしなくても異なる環境に動的に対応できるソフトウェアを作成します。 ソフトウェアを実行可能イメージとメッセージに分離します。メッセージには、操作中に印刷または表示 されるすべてのメッセージが含まれます。メッセージ文字列はメッセージデータベースに格納します。
アプリケーションを libc などのシステムライブラリにリンクする方法として、動的リンクと静的リンクを選択できます。 しかし、システムライブラリの国際化機能を必要とするアプリケーションは動的にリンクしなければなりません。 つまり、libc.a ではなく libc.so とリンクしなければなりません。
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() は ASCII の順序で照合を行うので、英語の場合でも a は Z の後になります。この順序が適切で ない場合もあります。一方、新しいライブラリルーチンの strcoll() と strxfrm() では、任意のソート 順序を作成できます。strcoll() は文字列の比較に使用し、strxfrm() は正しく照合できる文字列に変換 するために使用します。
テキスト処理を国際化および各国語対応する手順は次のとおりです。
#include <nl_types.h>
を追加し、catopen() を呼び出してカタログから文字列を取り出す。
catopen() 関数は以下の規則に従ってメッセージカタログを検索します。
#include <locale.h>
#include <nl_types.h>
nl_catd catd;
main() {
(void) setlocale(LC_ALL, "");
catd = catopen("demo", NL_CAT_LOCALE);
}
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) にインストールします。
アプリケーションのテキスト処理を国際化して各国語対応するには、以下の手順に従います。
32ビットアプリケーションは int、long およびポインタが32ビットである ILP32 データ型モデルに基づいているのに対し、 64ビットアプリケーションは long およびポインタが64ビットである LP64 データ型モデルに基づいています。
Solaris が32ビットまたは64ビット環境のどちらで動作しているかを調べるには、isainfo コマンドを使用します。
64ビットアプリケーションは64ビットカーネル上で動作します。32ビットアプリケーションは32カーネルおよび64ビットカーネルのどちらでも動作します。
アプリケーションを64ビットでコンパイルするには、cc コマンドに
-xarch=v9
(または
-xarch=generic64
)オプションを指定します。
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_t や uint_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 を実行すればラッパーが自動的に起動するアプリケーションを判定します。