前へ | 次へ | 目次 | 索引 |
複数のシステム間でソース・プログラムを移植する予定がある場合, HP C RTL を使用するための最後の準備作業の 1 つとして, HP C RTL と,C 言語の他のインプリメンテーションのランタイム・ライブラリの相違点を認識することが必要です。ここでは,OpenVMS システムとの間でプログラムを移植するときに発生する可能性のある問題の一部について説明します。移植性は HP C RTL のインプリメンテーションに密接に関係していますが,ここでは,他の HP C for OpenVMS 構造体の移植性についても説明します。
HP C RTL では, ANSI C で定義されているライブラリ関数をはじめ,一般に使用されている多くの API や,若干の OpenVMS 拡張機能も提供されます。特定の標準のうち, HP C RTL でインプリメントされている部分については, 第 1.5 節 を参照してください。可能な限り機能面で完全な移植性を維持するようになっています。 HP C RTL で提供される多くの標準 I/O および UNIX I/O の関数およびマクロは,他のインプリメンテーションの関数やマクロに機能的に対応します。
RTL 関数およびマクロの説明では,ここに示した問題の他に,ここに示していない問題についても詳しく説明しています。
次の一覧は,C プログラムを OpenVMS 環境に移植するときに考慮しなければならない問題点を示しています。
int foo 123; |
この初期化形式を使用するプログラムは変更する必要があります。
int a, b, c; |
a[i] = i++; |
x = func_y() + func_z(); |
f(p++, p++) |
HP C でも他の C コンパイラでも,このような式がすべての C コンパイラで同じ順序で評価されるという保証はありません。
HP C RTL では,リエントラントのサポートが向上し,強化されました。次の種類のリエントラントがサポートされます。
デフォルトのリエントラント・タイプは TOLERANT です。
リエントラント・タイプを設定するには, /REENTRANCY コマンド・ライン修飾子を指定してコンパイルするか, decc$set_reentrancy関数を呼び出します。 この関数は非 AST レベルから排他的に呼び出さなければなりません。
複数のスレッドまたは AST を使用するアプリケーションをプログラミングする場合は,次の 3 つのクラスの関数について考慮してください。
ほとんどの関数は,まったく内部データのない関数です。このような関数の場合,同期化が必要になるのは,パラメータがマルチスレッドのアプリケーションで使用されるか,または AST コンテキストと非 AST コンテキストの両方でパラメータが使用される場合だけです。たとえば, strcat関数は一般にはスレッド・セーフですが,次の例は安全でない使い方を示しています。
extern char buffer[100]; void routine1(char *data) { strcat( buffer, data ); } |
routine1が複数のスレッドで並列に実行されるか,または routine1がそのルーチンを呼び出す AST ルーチンによって割り込まれると, strcat呼び出しの結果は予測不能になります。
2 番目のクラスの関数は,スレッドだけで有効な静的データを含む関数です。通常,これらの関数は,アプリケーションが文字列の格納領域を解放することを許可されていない状況で,文字列を返すライブラリ内のルーチンです。これらのルーチンはスレッド・セーフですが,AST リエントラントではありません。つまり,並列に呼び出しても安全ですが,各スレッドはそれぞれ独自のデータのコピーを保有します。同じルーチンが非 AST コンテキストで実行される可能性がある場合は,これらのルーチンを AST ルーチンから呼び出すことはできません。このクラスのルーチンは次のとおりです。
asctime stat ctermid strerror ctime strtok cuserid VAXC$ESTABLISH gmtime the errno variable localtime wcstok perror |
使用している TCP/IP 製品がスレッド・セーフの場合,すべてのソケット関数もこのリストに含まれます。
3 番目のクラスの関数は,プロセス単位のデータに影響する関数です。これらの関数はスレッド・セーフではなく,AST リエントラントでもありません。たとえば, sigsetmaskはプロセス単位のシグナル・マスクを確立します。次のようなルーチンについて考えてみましょう。
void update_data base() { int old_mask; old_mask = sigsetmask( 1 << (SIGINT - 1)); /* Do work here that should not be aborted. */ sigsetmask( old_mask ); } |
update_databaseが複数のスレッドで並列して呼び出された場合,スレッド 2 が強制終了されない作業をまだ実行している間に,スレッド 1 は SIGINT のブロックを解除する可能性があります。
このクラスのルーチンは次のとおりです。
一般に, UTC ベースの時刻関数はメモリ内のタイム・ゾーン情報に影響を与える可能性があり,これはプロセス単位のデータです。しかし,アプリケーションが実行されている間,システム・タイム・ゾーンが変化せず ( これは一般的な場合です ),タイム・ゾーン・ファイルのキャッシュが許可されている場合 ( これはデフォルトです ),時刻関数 asctime_r, ctime_r, gmtime_r, localtime_rの _rバリアントはスレッド・セーフであり,かつ AST リエントラントです。 しかし,アプリケーションの実行中にシステム・タイム・ゾーンが変化する可能性がある場合や,タイム・ゾーン・ファイルのキャッシュが許可されていない場合は, UTC ベースの時刻関数のバリアントはどちらも 3 番目のクラスの関数に属し,スレッド・セーフでも AST リエントラントでもありません。 |
同じアプリケーション内でマルチスレッド・プログラミング・モデルと OpenVMS AST プログラミング・モデルを混在させることは推奨できません。アプリケーションで,どのスレッドが AST によって割り込まれるかを制御することはできません。この結果,AST ルーチンからも必要とされるリソースをスレッドが保有している場合,リソースのデッドロックが発生します。次のルーチンはミューテックスを使用します。リソース・デッドロックの発生を回避するには,マルチスレッド・アプリケーションで AST ルーチンからこれらを呼び出さないようにしなければなりません。
1.10 64 ビット・ポインタのサポート (Alpha only)
このセクションの説明は, OpenVMS Alpha バージョン 7.0 以降で 64 ビット仮想メモリ・アドレッシングを使用する必要のあるアプリケーション開発者を対象にしています。
OpenVMS Alpha の 64 ビット仮想アドレッシングのサポートでは, Alpha アーキテクチャで定義されている 64 ビット仮想アドレス空間が OpenVMS オペレーティング・システムとそのユーザの両方から使用できるようになっています。また,従来の 32 ビットの制限を超えて動的にマッピングされたデータにアクセスするために,プロセス単位の仮想アドレッシングも可能です。
OpenVMS Alpha バージョン 7.0 以降のシステムの HP C ランタイム・ライブラリでは, 64 ビット・ポインタをサポートするために次の機能が提供されます。
前へ | 次へ | 目次 | 索引 |