日本-日本語

製品  >  ソフトウェア  >  OpenVMS  >  マニュアル

OpenVMS マニュアル


≫ 

OpenVMS
ライブラリ

タイトルページ
目次
まえがき
第 1 章:移行プロセスの概要
第 2 章:移行方法の選択
第 3 章:アプリケーションの移行
第 4 章:再コンパイルと再リンクの概要
第 5 章:ページサイズの拡大に対するアプリケーションの対応
第 6 章:共用データの整合性の維持
第 7 章:アプリケーションデータ宣言の移植性の確認
第 8 章:アプリケーション内の条件処理コードの確認
第 9 章:OpenVMS I64コンパイラ
付録 A :アプリケーション評価チェックリスト
用語集
索引
PDF
OpenVMS ホーム

HP OpenVMS
OpenVMS VAX から OpenVMS I64 への
アプリケーションの移行


目次 索引



アプリケーションが実行するメモリ割り当てを変更しなければならないかどうかを判断するには,メモリがどこで割り当てられるかを確認しなければなりません。メモリ割り当てを実行するシステム・サービス・ルーチン ($EXPREG と $CRETVA) を使用すると,次の 2 種類の方法でメモリを割り当てることができます。

  • アプリケーションの仮想アドレス空間の P0 領域または P1 領域のサイズを拡張する方法

  • 指定した位置から始まる,アプリケーションの既存の仮想アドレス空間の領域を再要求する方法

Intel Itanium アーキテクチャでは,VAX アーキテクチャと同じ仮想アドレス空間レイアウトを定義しており,VAX システムの場合と同じ方向に P0 領域と P1 領域を拡大できます。 図 5-1 はこのレイアウトを示しています。

図 5-1 仮想アドレスのレイアウト




アプリケーションで $EXPREG システム・サービスを使用して仮想アドレス空間を拡張することによりメモリを割り当てる場合には,ソース・コードを変更する必要はありません。これは,VAX システムで引数として指定した値が I64 システムでも正しく動作するからです。この理由は次のとおりです。

  • I64 システムでは,$EXPREG システム・サービスは要求されたメモリのサイズ (pagcnt 引数でページ・カウントとして指定した値) を 512 バイト単位と解釈します。これは VAX システムの場合と同じです。したがって,アプリケーションで指定した値は同じサイズのメモリを要求します。ただし,システム・サービスはページ・カウントを CPU 固有のページに切り上げるため,アプリケーションに対してシステムが実際に割り当てるメモリ・サイズは,VAX システムの場合より I64 システムの場合の方が大きくなる可能性があります。割り当てられたメモリ全体はアプリケーションで使用できます。アプリケーションは通常,必要なバッファを確保するためにメモリを割り当てます。しかし,バッファのサイズは各プラットフォームで変化しないため,指定した値はアプリケーションの必要条件を満足できます。

  • 割り当ては仮想アドレス空間の拡張された領域で実行されるため,要求したサイズとシステムが実際に割り当てたサイズに違いがあっても,アプリケーションの機能に影響を与えません。

対処方法

アプリケーションを変更する必要はありません。しかし,$EXPREG システム・サービスが返すメモリ・サイズは, Intel Itanium アーキテクチャを実現した各システムで異なる可能性があるため,システムが割り当てた正確なメモリ範囲を確認しておくことをお勧めします。正確なメモリ範囲を確認するには,$EXPREG システム・サービスに対して省略可能な引数である retadr 引数を指定します (アプリケーションでこの引数がまだ指定されていない場合)。 retadr 引数には,システム・サービスが割り当てたメモリの先頭アドレスと末尾アドレスが格納されます。

たとえば, 例 5-1 のプログラムは, $EXPREG システム・サービスを呼び出すことにより 10 ページの追加メモリを要求します。このプログラムを VAX システムで実行した場合には, $EXPREG システム・サービスは 5120 バイトの追加メモリを割り当てます。このプログラムを I64 システムで実行した場合には, $EXPREG システム・サービスは少なくとも 8192 バイトを割り当てます。また,Intel Itanium アーキテクチャの特定の実装でのページ・サイズによっては,それ以上のサイズのメモリを割り当てることもあります。

例 5-1 仮想アドレス空間の拡張によるメモリの割り当て

#include  <ssdef.h> 
#include  <stdio.h> 
#include  <stsdef.h> 
#include  <descrip.h> 
#include  <dvidef.h> 
 
#define  PAGE_COUNT 10  (1)
#define  P0_SPACE   0 
#define  P1_SPACE   1 
 
main( argc, argv ) 
int argc; 
char *argv[]; 
{ 
     int    status = 0; 
     long   bytes_allocated, addr_returned[2]; 
 
(2)   status = SYS$EXPREG( PAGE_COUNT, &addr_returned, 0, P0_SPACE); 
 
     bytes_allocated = addr_returned[1] - addr_returned[0]; 
 
     if( status == SS$_NORMAL) 
        printf("bytes allocated = %d\n", bytes_allocated ); 
     else 
        return (status); 
         
} 

以下の項目は, 例 5-1 に示した番号に対応します。

  1. この例では,要求するページ数を意味するシンボルとして PAGE_COUNT を定義しています。

  2. この例では,仮想アドレス空間の P0 領域の末尾に 10 ページを追加することを要求しています。



5.2.2 既存の仮想アドレス空間でのメモリの割り当て

アプリケーションで $CRETVA システム・サービスを使用することにより,仮想アドレス空間内のメモリを再割り当てする場合には, $CRETVA に対する引数のうち,次の引数の値を変更しなければならない場合があります。

  • VAX ページ境界にアラインするために,inadr 引数に指定するアドレスを 512 の倍数になるように明示的に調整している場合には,アドレスを変更しなければなりません。 I64 システムでは,$CRETVA システム・サービスが先頭アドレスを CPU 固有のページ境界に合わせて切り捨てますが,この値は各システムで異なります。

  • inadr 引数にアドレス範囲指定によって再割り当てされるサイズは, I64 システムでは VAX システムの場合より大きくなる可能性があります。これは,要求が CPU 固有のページ・サイズに合わせて切り上げられるためです。この結果,隣接データが破壊される可能性があります。これは 1 ページを割り当てる場合でも発生します (inadr 引数に指定した先頭アドレスと末尾アドレスが一致する場合には, 1 ページが割り当てられます)。

対処方法

アプリケーションを変更しなければならないかどうかを判断するには,次のことを行ってください。

  • 可能性のあるすべてのページ・サイズに対して,仮想アドレス空間の中で呼び出しの影響を受ける領域が重要なデータを破壊しないことを確認してください。

  • 可能性のあるすべてのページ・サイズに対して,割り当てが開始される先頭アドレスが常にページ境界にアラインされることを確認してください。

  • 省略可能な retadr 引数がアプリケーションで指定されていない場合には,この引数を指定して,$CRETVA システム・サービスに対する呼び出しで割り当てられた正確なメモリの範囲を判断してください。

例 5-2 は,バッファに割り当てたメモリを $CRETVA システム・サービスによって再割り当てする方法を示しています。

例 5-2 既存のアドレス空間でのメモリの割り当て

#include  <ssdef.h> 
#include  <stdio.h> 
#include  <stsdef.h> 
#include  <descrip.h> 
#include  <dvidef.h> 
 
char _align(page) buffer[1024]; 
 
main( argc, argv ) 
int argc; 
char *argv[]; 
{ 
 
     int      status = 0; 
     long     inadr[2]; 
     long     retadr[2]; 
 
     inadr[0] = &buffer[0]; 
     inadr[1] = &buffer[1023]; 
 
     printf("inadr[0]=%u,inadr[1]=%u\n",inadr[0],inadr[1]); 
 
     status = SYS$CRETVA(inadr, &retadr, 0); 
 
     if( status & STS$M_SUCCESS ) 
     { 
        printf("success\n"); 
        printf("retadr[0]=%u,retadr[1]=%u\n",retadr[0],retadr[1]); 
     } 
     else 
     { 
        printf("failure\n"); 
        exit(status); 
     } 
} 



5.2.3 仮想メモリの削除

$EXPREG システム・サービスと $CRETVA システム・サービスによって割り当てたメモリを解除するために $DELTVA システム・サービスを呼び出す場合, retadr 引数で返されたアドレス範囲 (メモリを割り当てるために使用したルーチンから返された値) を $DELTVA システム・サービスの inadr 引数として使用しているときは,アプリケーションを変更する必要はありません。実際に割り当てられるサイズは各システムで異なるため,割り当ての範囲に関してアプリケーションで何らかの仮定を行うことは望ましくありません。

5.3 メモリ・マッピング・ルーチンの確認

アプリケーションで実行するメモリ・マッピングを変更しなければならないかどうかを判断するには,アプリケーションが仮想メモリのどの部分でマッピングを実行するかを確認しなければなりません。メモリ・マッピング・システム・サービス ($CRMPSC と $MGBLSC) を使用すると,次の方法でメモリをマッピングできます。

  • アプリケーションの仮想アドレス空間の拡張領域にメモリをマッピングする方法

  • 指定した位置からはじまるアプリケーションの仮想アドレス空間に,メモリの 1 ページをマッピングする方法 (この位置は既存の仮想アドレス空間に存在してもかまいません)

  • 仮想アドレス空間の中の指定した先頭アドレスと末尾アドレスによって定義される既存の領域に,メモリをマッピングする方法

アプリケーションがセクションをマッピングする方法は,主に $CRMPSC システム・サービスと $MGBLSC システム・サービスに対する次の引数によって決まります。

  • inadr 引数は,セクションのサイズと位置を先頭アドレスと末尾アドレスによって指定します。 $CRMPSC システム・サービスはこの引数を次の方法で解釈します。

    • inadr 引数に指定した 2 つのアドレスがどちらも同じであり, flags 引数の SEC$M_EXPREG ビットがオンの場合には,指定したアドレスが含まれるプログラム領域でメモリが割り当てられますが,指定した位置は使用されません。

    • inadr 引数に指定されているアドレスがどちらも同じであり, SEC$M_EXPREG フラグがオフの場合には,指定した位置を先頭アドレスとして 1 ページがマッピングされます ($CRMPSC システム・サービスのこの動作モードは I64 システムではサポートされません。アプリケーションでこのモードを使用している場合には,ソース・コードの変更方法に関して 第 5.3.2 項 を参照してください)。

    • 2 つのアドレスが異なる場合には,指定した境界を使用して,セクションがメモリにマッピングされます。

  • pagcnt (ページ・カウント) 引数は,セクション・ファイルからマッピングするブロック数を指定します。

  • relpag (相対ページ番号) 引数は,セクション・ファイルの中でマッピングを開始する位置を指定します。

$CRMPSC システム・サービスと $MGBLSC システム・サービスは,少なくとも CPU 固有のページを 1 ページ分マッピングします。セクション・ファイルが 1 ページ未満の場合には,ページの残りの部分には 0 が格納されます。ページの残りの領域はアプリケーションで使用しないでください。なぜなら,セクション・ファイルに格納できるデータだけがディスクに書き戻されるためです。

5.3.1 拡張した仮想アドレス空間へのマッピング

アプリケーションの仮想アドレス空間の拡張領域にセクション・ファイルをマッピングしている場合には,ソース・コードを変更する必要はありません。これは,拡張された仮想アドレス空間にマッピングされるため,たとえ I64 システムで割り当てられるメモリのサイズが VAX システムより大きくても,既存のデータの上にマッピングされる危険性がないためです。そのため, VAX システムで $CRMPSC システム・サービスに対して引数として指定した値は, I64 システムでも正しく機能します。

対処方法

セクションを仮想メモリの拡張領域にマッピングするアプリケーションは,変更しなくても正しく動作しますが,アプリケーションで retadr 引数を指定していない場合には,この引数を指定し,呼び出しによってマッピングされたメモリの正確な範囲を確認してください。

注意

アプリケーションで relpag 引数を指定する場合には, retadr 引数も指定しなければなりません。これは省略可能な引数ではありません。 relpag 引数の使用についての詳細は, 第 5.3.4 項 を参照してください。

例 5-3 は,セクション・ファイルを拡張アドレス空間にマッピングする $CRMPSC システム・サービスの呼び出しを示しています。この例では,次に示すように DCL の CREATE コマンドを使用して作成された MAPTEST.DAT という名前のセクション・ファイルをマッピングします。


$  CREATE maptest.dat 
test data test data test data test data test data 
test data test data test data test data test data 
test data test data test data test data test data 
test data test data test data test data test data 
test data test data test data test data test data 
test data test data test data test data test data 
test data test data test data test data test data 
test data test data test data test data test data 
[Ctrl/Z]

例 5-3 拡張された仮想アドレス空間へのセクションのマッピング

#include  <ssdef.h> 
#include  <string.h> 
#include  <stdlib.h> 
#include  <stdio.h> 
#include  <stsdef.h> 
#include  <descrip.h> 
#include  <dvidef.h> 
#include  <rms.h> 
#include  <secdef.h> 
 
struct FAB fab; 
 
char _align(page) buffer[1024]; 
char *filename = "maptest.dat"; 
 
main( argc, argv ) 
int argc; 
char *argv[]; 
{ 
 
     int    status = 0; 
     long   flags = SEC$M_EXPREG; 
     long   inadr[2]; 
     long   retadr[2]; 
     int    fileChannel; 
 
/********  create disk file to be mapped *************/ 
 
     fab = cc$rms_fab; 
     fab.fab$l_fna = filename; 
     fab.fab$b_fns = strlen( filename ); 
     fab.fab$l_fop = FAB$M_CIF | FAB$M_UFO;  /* must be UFO */ 
 
     status = sys$create( &fab ); 
 
     if( status & STS$M_SUCCESS ) 
        printf("%s opened\n",filename); 
     else 
     { 
        exit( status ); 
     } 
 
     fileChannel = fab.fab$l_stv; 
 
/**********  create and map the section  ****************/ 
 
     inadr[0] = &buffer[0]; 
     inadr[1] = &buffer[0]; 
 
     status = SYS$CRMPSC( inadr, /* inadr=address target for map */ 
                        &retadr, /* retadr= what was actually mapped */ 
                              0, /* acmode  */ 
                          flags, /* flags, with SEC$M_EXPREG bit set */ 
                              0, /* gsdnam, only for global sections */ 
                              0, /* ident, only for global sections */ 
                              0, /* relpag, only for global sections */ 
                    fileChannel, /* returned by SYS$CREATE */ 
                              0, /* pagcnt = size of sect. file used */ 
                              0, /* vbn = first block of file used */ 
                              0, /* prot = default okay */ 
                              0); /* page fault cluster size */ 
 
     if( status & STS$M_SUCCESS ) 
     { 
          printf("section mapped\n"); 
          printf("retadr[0]=%u,retadr[1]=%u\n",retadr[0],retadr[1]); 
     } 
     else 
     { 
          printf("map failed\n"); 
          exit( status ); 
     } 
 
} 



5.3.2 特定の位置への単一ページのマッピング

アプリケーションでセクション・ファイルを 1 ページのメモリにマッピングしていた場合には, I64 システムではこの操作モードがサポートされないため,ソース・コードを変更しなければなりません。 I64 システムのページ・サイズは VAX システムのページ・サイズと異なっており,さらに Intel Itanium アーキテクチャの実装ごとにも異なるため,セクション・ファイルをマッピングするための正確なメモリ境界を指定しなければなりません。このような使い方をした場合,$CRMPSC システム・サービスは,引数が誤っていることを示すエラー (SS$_INVARG) を返します。

アプリケーションでこのモードを使用しているかどうかを判断するには, inadr 引数に指定した先頭アドレスと末尾アドレスを確認します。両方のアドレスが同じであり,flags 引数の SEC$M_EXPREG ビットがオフの場合には,アプリケーションはこのモードを使用しています。

対処方法

このモードの $CRMPSC システム・サービスの呼び出しを変更する場合には,次のガイドラインに従ってください。

  • マッピングの宛先となる位置が重要でない場合には, flags 引数の SEC$M_EXPREG ビットをオンにし,システム・サービスがアプリケーションの仮想アドレス空間の拡張領域にセクション・ファイルをマッピングするようにしてください。この操作モードについての詳細は, 第 5.3.1 項 を参照してください。

  • マッピングの宛先となる位置が重要な場合には, inadr 引数の先頭アドレスと末尾アドレスの両方を定義し,定義した領域にセクションをマッピングしてください。このモードについての詳細は, 第 5.3.3 項 参照してください。



5.3.3 定義されたアドレス範囲へのマッピング

アプリケーションで仮想アドレス空間の定義された領域にセクションをマッピングしている場合には,ソース・コードを変更しなければならない可能性があります。これは,I64 システムでは $CRMPSC システム・サービスおよび $MGBLSC システム・サービスが VAX システムと異なる方法で一部の引数を解釈するためです。相違点は次のとおりです。

  • inadr 引数に指定する先頭アドレスは, CPU 固有のページ境界にアラインされていなければならず,指定する末尾アドレスも CPU 固有のページの末尾にアラインされていなければなりません。 VAX システムでは, $CRMPSC システム・サービスおよび $MGBLSC システム・サービスは,これらのアドレスを調整して,ページ境界にアラインされるようにします。 I64 システムでは,このようなアドレスの調整は実行されません。これは,ページ・サイズがはるかに大きいため, CPU 固有のページ境界にアドレスを調整すると,メモリのより大きな部分に影響があるからです。したがって,I64 システムでは,仮想メモリ空間のどこにマッピングするかを明示的に指定しなければなりません。指定したアドレスが CPU 固有のページ境界にアラインされていない場合には, $CRMPSC システム・サービスは,引数が誤っていることを示すエラー (SS$_INVARG) を返します。

  • retadr 引数に返されるアドレスは,呼び出しで実際にマッピングされたメモリの中で使用可能な部分だけを反映し,マッピングされたメモリ全体を反映するわけではありません。使用可能なサイズとは, pagcnt 引数に指定した値 (ページレット単位の値) と,セクション・ファイルのサイズのうち,どちらか小さい方の値です。実際にマッピングされるサイズは,セクション・ファイルをマッピングするために CPU 固有のページが何ページ必要であるかに応じて変わります。セクション・ファイルが CPU 固有のページより小さい場合には,ページの残りの部分に 0 が挿入されます。このページの残りの空間をアプリケーションで使用しないでください。 retadr 引数で指定する末尾アドレスは,アプリケーションで使用できる上限を指定します。また,relpag 引数を指定するときは retadr 引数も指定しなければなりません。 I64 システムでは,この引数は VAX システムでのように省略可能ではありません。詳細は, 第 5.3.4 項 を参照してください。

対処方法

可能な場合には,拡張された仮想アドレス空間にデータをマッピングするように,アプリケーションを変更してください。アプリケーションがデータをマッピングする方法を変更できない場合には,次のガイドラインに従ってください。

  • オペレーティング・システムは少なくとも 1 物理ページをマップします。 I64 システム上の物理ページのサイズは VAX システムより大きいため,アプリケーションの中で定義したバッファにセクションをマップする場合,隣接するデータが上書きされないよう注意してください。多くの VAX システム上のアプリケーションでは,たとえマップされるセクション・ファイルのサイズが 512バイト以下でも,セクションがマップされるバッファのサイズを VAX システムのページ・サイズである 512 バイト単位で定義しています。 I64 でこの方針に従うためには,メモリが無駄になりますが,アプリケーションでバッファのサイズを 64K バイト単位で宣言してください。
    セクションをマップするときに,隣接データが重ね書きされないことを確認するためのよりよい方法は,バッファを独立したイメージ・セクションに格納するようにリンカに指示することです。 (リンカはイメージをイメージ・セクションから作成します。それぞれのイメージ・セクションは,イメージの各部分のメモリの必要量を定義しています。) リンカはイメージ・セクションをページ境界に配置し,隣接するデータは次のページ境界から配置します。このため,バッファを個別のイメージ・セクションに分離することで,マッピング操作によって隣接データが重ね書きされないことが保証されます。このように,隣接するデータを破壊したり,バッファのサイズを変更することなく, 1 ページ分のメモリをセクションにマップすることが可能です。
    リンカがセクション・ファイルを個別のイメージ・セクションに置いたことを確認するために,リンカの PSECT_ATTR= オプションを使用して,プログラム・セクションの SOLITARY 属性を設定しなければなりません (詳細は,『OpenVMS Linker Utility Manual』を参照してください)。また,使用している高級または中級のプログラミング言語の機能を使用して,定義したバッファが個別のプログラム・セクションに配置されていることを確認しなければならない場合があります。詳細は,コンパイラのマニュアルを参照してください。

  • $CRMPSC システム・サービスと $MGBLSC システム・サービスの引数として指定するセクションの先頭アドレスおよび末尾アドレスが, CPU 固有のページの先頭アドレスおよび末尾アドレスにアラインされることを確認してください。 VAX システムでは,ページ境界に合わせてアドレスが調整されます。 I64 システムでは,ユーザが指定したアドレスはページ境界に合わせて調整されません。
    SOLITARY プログラム・セクション属性を使用して,セクションを個別のイメージ・セクションに分離すると,先頭アドレスはページ境界にアラインされます。これは,実行時のホスト・マシンのページ・サイズにかかわらず,リンカがデフォルトでイメージ・セクションをページ境界にアラインするためです。
    セクションの末尾アドレスが CPU 固有のページ境界にアラインされていることを確認するためには,アプリケーションを実行するマシンがサポートしているページ・サイズを知る必要があります。 $GETSYI システム・サービスや LIB$GETSYI ランタイム・ライブラリ・ルーチンを呼ぶことにより,実行時に CPU 固有のページ・サイズを得ることができます。得た値を使ってアラインされた末尾アドレスの値を計算し,システム・サービスの inadr 引数に渡すことができます。
    システムがマップした使用可能なメモリ量を確認するためには, retadr 引数を指定してください。アプリケーションがページの一部分しか使用しない場合でも,オペレーティング・システムは最低でも 1 ページをマップします。 retadr 引数が示す末尾アドレスは,使用できるメモリの上限を示します。(I64 システムでは, $CRMPSC システム・サービスで relpag 引数を指定する場合,必ず retadr 引数も指定しなければなりません。)


目次 索引

印刷用画面へ
プライバシー 本サイト利用時の合意事項