日本-日本語

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

OpenVMS マニュアル


≫ 

OpenVMS
ライブラリ

タイトルページ
目次
まえがき
第 1 章:はじめに
第 2 章:ページサイズの拡大に対するアプリケーションの対応
第 3 章:共有データの整合性の維持
第 4 章:アプリケーションデータ宣言の移植性の確認
第 5 章: アプリケーション内の条件処理コードの確認
第 6 章:ネイティブイメージとトランスレートイメージの相互操作性の確認
付録 A :OpenVMS AXPコンパイラ
索引
PDF
OpenVMS ホーム
OpenVMS AXP オペレーティング・システム | HPE 日本(日本ヒューレット・パッカード株式会社)

OpenVMS AXP
オペレーティング・システム
OpenVMS AXP オペレーティング・システムへの移行:
再コンパイルと再リンク


目次 索引




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

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

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

対処方法

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

  • オペレーティング・システムは少なくとも1物理ページをマップします。AXPシステム上の物理ページのサイズはVAXシステムより大きいため,アプリケーションの中で定義したバッファにセクションをマップする場合,隣接するデータが重ね書きされて破壊されないよう注意してください。多くの VAXシステム上のアプリケーションでは,たとえマップされるセクション・ファイルのサイズが512バイト以下でも,セクションがマップされるバッファのサイズをVAX システムのページ・サイズである512バイト単位で定義しています。AXPでこの方針に従うためには,アプリケーションでバッファのサイズを64Kバイト単位で定義してください。

    セクションがマップされるときに,隣接データが重ね書きされないことを確認するためのよりよい方法は,リンカにバッファを独立したイメージ・セクションとして指定することです(リンカはイメージをイメージ・セクションから作成します。それぞれのイメージ・セクションは,イメージの各部分のメモリの必要量を定義しています)。リンカはイメージ・セクションをページ境界に配置し,隣接するデータはつぎのページ境界から配置します。このためバッファを独自のイメージ・セクションに独立されることによって,隣接データがマッピング操作によって重ね書きされないことが保証されます。このように,隣接するデータを破壊したり,バッファのサイズを変更することなく1ページ分のメモリをセクションにマップすることが可能です。

    リンカがセクション・ファイルを独自のイメージ・セクションに置いたことを確認するために,リンカのPSECT_ATTRオプションを使用してSOLITARYプログラム・セクション属性を設定する必要があります(詳しくは『OpenVMS Linker Utility Manual』を参照してください)。また,使用している高級または中級のプログラミング言語を,コンパイラが定義したバッファを別のプログラム・セクションに置くことを確認するために,使用する必要があるかもしれません。詳しくは,コンパイラの解説書を参照してください。

  • $CRMPSCKと$MGBLSCシステム・サービスの値として指定する先頭または末尾アドレスが,CPU固有ページの先頭または末尾アドレスとともにアラインされることを確認してください。VAXシステムでは,システム・サービスはアドレスがページ境界にそろうように調整します。AXPシステムでは,システム・サービスは,ユーザが指定したアドレスをページ境界にそろうように調整しません。

    セクションを独自のイメージ・セクションに分離する場合には,SOLITARYプログラム・セクション属性を使用して,先頭アドレスはページ境界にアラインされます。これは,実行時のホスト・マシンのページ・サイズにかかわらず,リンカが省略時の設定によりイメージ・セクションをページ境界にアラインするからです。

    セクションの末尾アドレスがCPU固有のページ境界にアラインされたことを確認するためには,アプリケーションを実行しているマシンがサポートしているページ・サイズを知る必要があります。$GETSYI システム・サービスや LIB$GETSYI ランタイム・ライブラリ・ルーチンを呼ぶことにより,実行時にCPU固有のページ・サイズを得ることができます。また,得た値を使ってアラインされた末尾アドレスの値を計算し,inadr引数内でシステム・サービスに渡すこともできます。

    システムがマップした使用可能なメモリ量を判断するためには,retadr 引数を指定してください。たとえアプリケーションがページの一部分しか使用しないとしても,オペレーティング・システムは最低でも1ページをマップします。retadr 引数で指定された末尾アドレスは使用できるメモリの上限を示します(AXPシステムでアプリケーションが$CRMPSCシステム・サービスに relpag 引数を指定する場合,必ず retadr 引数を指定しなければなりません)。

たとえば,例 2-4 に示すVAXプログラムは,第 2.3.1 項 で作成したセクション・ファイルを既存の仮想アドレス空間にマッピングします。アプリケーションはbufferという名前のバッファを定義します。このバッファのサイズは512バイトであり,これは VAXのページ・サイズを反映しています。プログラムはバッファの1バイト目のアドレスを先頭アドレスとして,また,バッファの最終バイトのアドレスを末尾アドレスとして inadr 引数に渡すことにより,セクションの正確な境界を定義します。

例 2-4 仮想アドレス空間の定義された領域へのセクションのマッピング

#include <ssdef.h> 
#include <stdio.h> 
#include <stsdef.h> 
#include <descrip.h> 
#include <dvidef.h> 
#include <rms.h> 
#include <secdef.h> 
 
struct FAB fab; 
 
char *filename = "maptest.dat"; 
 
char _align(page)buffer[512]; 
 
main(argc, argv)
int argc; 
char *argv[]; 
{ 
 
     int    status = 0; 
     long   flags = 0; 
     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("Opened mapfile %s\n",filename); 
     else 
     { 
        printf("Cannot open mapfile %s\n",filename); 
        exit(status); 
     } 
 
     fileChannel = fab.fab$l_stv; 
 
/**********  create and map the section  ****************/ 
 
     inadr[0] = &buffer[0]; 
     inadr[1] = &buffer[511]; 
 
     printf("inadr[0]=%u,inadr[1]=%u\n",inadr[0],inadr[1]); 
 
     status = SYS$CRMPSC(inadr, /* inadr=address target for map */ 
                         &retadr, /* retadr= what was actually mapped */ 
                               0, /* acmode  */ 
                               0, /* flags */ 
                               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("Map succeeded\n"); 
           printf("retadr[0]=%u,retadr[1]=%u\n",retadr[0],retadr[1]); 
     } 
     else 
     { 
           printf("Map failed\n"); 
           exit(status); 
     } 
 
} 

例 2-4 に示したプログラムをAXPシステムで正しく実行するには,次の変更が必要です。

  • inadr 引数に指定するセクションの先頭アドレスがAXPのページ境界にアラインされることと,指定する末尾アドレスがAXPページの末尾にアラインされることを確認しなければなりません。

  • AXPシステムの大きいページをマッピングするときに,隣接データの上に重ね書きされないことを確認しなければなりません。

これらの目標を達成するための1つの方法として,SOLITARYプログラム・セクション属性を使用することにより,セクション・データを格納したプログラム・セクションを独自のイメージ・セクションに分離する方法があります。

この例では,bufferという名前のセクションはbufferという名前のプログラム・セクション内に示されています(プログラム・セクションの生成方法は,各プラットフォーム上の言語の種類により異なります。セクションが独自のプログラム・セクションにあることをコンパイラの解説書で確認してください)。次のリンク操作は,このプログラム・セクションのSOLITARY属性を設定する方法を示しています。


$  LINK MAPTEST, SYS$INPUT/OPT 
PSECT_ATTR=BUFFER,SOLITARY 
[Ctrl/Z]

CPU固有のページ境界の末尾にアラインされる末尾アドレスをセクション・バッファに対して指定するには,実行時にCPU固有のページ・サイズを入手し,その値から1を減算し,その値を使用して配列の最終要素のアドレスを求めます。この値をinadr引数の2番目のロングワードとして渡します(実行時にページ・サイズを判断する方法については,第 2.4 節 を参照してください)。セクションがマッピングされるバッファの割り当てを変更する必要はありません。

アプリケーションが任意のページ・サイズのAXPシステムで正しく実行されるようにするには,/BPAGE=16修飾子を指定することにより,リンカがイメージ・セクションを64KBの境界に強制的にアラインするようにします。実際にマッピングされるメモリの総量は,使用可能なメモリの合計よりはるかに大きくなる可能性があります。使用可能なメモリのサイズは,ページ・カウント( pagcnt )引数の値とセクション・ファイルのサイズのうち,どちらか小さい方の値によって決定されます。セクションの範囲内に含まれないメモリを使用しないようにするには,retadr 引数に戻された値を使用します。

例 2-5 は,AXPシステムで正しく実行するために 例 2-4 に対して必要なソースの変更を示しています。

例 2-5 例 2-4をAXPシステムで実行するのに必要なソース・コードの変更

#include  <ssdef.h> 
#include  <stdio.h> 
#include  <stsdef.h> 
#include  <string.h> 
#include  <stdlib.h> 
#include  <descrip.h> 
#include  <dvidef.h> 
#include  <rms.h> 
#include  <secdef.h> 
#include  <syidef.h> (1)
 
char buffer[512];  (2)
char *filename = "maptest.dat"; 
struct FAB fab; 
 
long  cpu_pagesize; (3)
 
struct itm {                      /* item list */ 
    short int     buflen;  /* length of buffer in bytes */ 
    short int  item_code;  /* symbolic item code */ 
    long          bufadr;  /* address of return value buffer */ 
    long       retlenadr;  /* address of return value buffer length */ 
  } itmlst[2]; (4)
 
main(argc, argv)
int argc; 
char *argv[]; 
{ 
     int    i; 
     int    status = 0; 
     long   flags = SEC$M_EXPREG; 
     long   inadr[2]; 
     long   retadr[2]; 
     int    fileChannel; 
     char  *mapped_section; 
 
/********  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; 
 
/**********  obtain the page size at run time  ****************/ 
 
 
     itmlst[0].buflen =  4; 
     itmlst[0].item_code = SYI$_PAGE_SIZE;    
     itmlst[0].bufadr =  &cpu_pagesize;       
     itmlst[0].retlenadr = &cpu_pagesize_len; 
     itmlst[1].buflen = 0; 
     itmlst[1].item_code = 0;  
 
(5)   status = sys$getsyiw(0, 0, 0, &itmlst, 0, 0, 0); 
 
     if(status & STS$M_SUCCESS)
     { 
          printf("getsyi succeeds, page size = %d\n",cpu_pagesize); 
     } 
     else 
     { 
          printf("getsyi fails\n"); 
          exit(status); 
     } 
 
/**********  create and map the section  ****************/ 
 
     inadr[0] = &buffer[0]; 
     inadr[1] = &buffer[cpu_pagesize - 1]; (6) 
 
     printf("address of buffer = %u\n", inadr[0]); 
 
     status = SYS$CRMPSC(&inadr, /* inadr=address target for map */ 
                        &retadr, /* retadr= what was actually mapped */ 
                              0, /* acmode  */ 
                              0, /* noflags to 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("start address returned =%u\n",retadr[0]); 
     } 
     else 
     { 
          printf("map failed\n"); 
          exit(status); 
     } 
} 

次のリストの各項目は,例 2-5 の番号に対応しています。

  1. ヘッダ・ファイルSYIDEF.Hには,$GETSYIシステム・サービスに対する OpenVMSアイテム・コードの定義が登録されています。

  2. バッファは__align(page)ストレージ記述子を使用せずに定義されています。ページ・サイズはOpenVMS AXPシステムで実行するまで判断できないため,DEC C for OpenVMS AXPコンパイラは,__align(page)が指定されているときに,データをAXPの最大ページ・サイズ(64KB)にアラインします。

  3. この構造は,実行時にページ・サイズを入手するために使用される項目リストを定義します。

  4. この変数には,戻されたページ・サイズ値が格納されます。

  5. $GETSYIシステム・サービスに対するこの呼び出しでは,実行時にページ・サイズが入手されます。

  6. バッファの末尾アドレスは,戻されたページ・サイズ値から1を減算することにより指定されます。



2.3.4 オフセットによるセクション・ファイルのマッピング

アプリケーションではセクション・ファイルの一部だけをマッピングできます。その場合には,マッピングを開始するアドレスをセクション・ファイルの先頭からのオフセットとして指定します。このオフセットを指定するには,$CRMPSCシステム・サービスの relpag 引数に対して値を指定します。relpag 引数の値は,ファイルの先頭を基準にしてマッピングを開始するページ番号を指定します。

$CRMPSCシステム・サービスは互換性を維持するために,VAXシステムと AXPシステムの両方のシステムにおいて,relpag 引数の値を 512バイト単位で解釈します。しかし,AXPシステムのCPU固有のページ・サイズは512バイトより大きいため,relpag 引数にオフセットとして指定する値はおそらくCPU固有のページ境界にアラインされません。$CRMPSCシステム・サービスは仮想メモリをCPU固有のページ単位でのみマッピングできます。したがって,AXPシステムでは,セクション・ファイルのマッピングはオフセット・アドレスを含むCPU固有のページの先頭から開始され,オフセットによって指定されるアドレスから正確に開始されるわけではありません。

注意

ルーチンは,オフセットによって指定されるアドレスを含むCPU固有のページの先頭からマッピングを開始しますが,retadr 引数に戻される先頭アドレスはオフセットによって指定されたアドレスであり,実際にマッピングが開始されたアドレスではありません。

アプリケーションでオフセットからセクション・ファイルにマッピングする場合には,AXPシステムでマッピングされる余分な仮想メモリ空間を格納できるように,inadr 引数に指定されるアドレス範囲のサイズを拡大する必要があります。指定されるアドレス範囲が小さすぎる場合には,アプリケーションはセクション・ファイルの中で必要な部分全体をマッピングできない可能性があります。これは,マッピングがセクション・ファイルの先頭アドレスから開始されるからです。

たとえば,VAXシステムでセクション・ファイルをマッピングするときに,ブロック番号15から始まる16ブロックをマッピングする場合には,アドレス範囲として 16*512バイトのサイズを inadr 引数に指定し,relpag 引数に対して15を指定できます。これと同じマッピングをAXPシステムで実行するには,ページ・サイズの違いを考慮しなければなりません。たとえば,8Kバイト・ページ・サイズのAXPシステムでは,relpag オフセットによって指定されるアドレスは,図 2-2 に示すように,15ページレットをCPU固有の 1ページに格納できます。AXPシステムでは,$CRMPSCシステム・サービスはセクション・ファイルのマッピングをCPU固有のページ境界から開始するため,16番目から30番目までのブロックを正しくマッピングできません。マッピングを正しく実行するには,AXPシステムで$CRMPSCシステム・サービス(または $MGBLSCシステム・サービス)がマッピングする追加の15ページレットを格納できるようにアドレス範囲のサイズを拡大しなければなりません。このようにサイズを拡大しなかった場合には,指定したセクション・ファイルの中で1ブロックだけしかマッピングされません。図 2-2 はこの状況を示しています。

図 2-2 オフセットによるマッピングに対してアドレス範囲が与える影響


relpag 引数に指定するアドレス範囲をどれだけ拡大するかを計算する場合には,次の公式を使用すると便利です。この公式は,特定の数のページレットをマッピングするのに充分なCPU固有のページ数を計算します。


 (number_of_pagelets_to_map+(2*pagelets_per_page)-2) 
                   pagelets_per_page

たとえば,この公式を使用すれば,前の例に指定したアドレス範囲をどれだけ拡大すればよいかを計算できます。次の式では,ページ・サイズは8Kであると仮定しています。したがって,pagelets_per_page は16になります。


16+((2x16)-2)/16=2.87... 

結果をもっとも近い整数に切り捨てることにより,この公式は inadr 引数に指定するアドレス範囲が,CPU固有のページの2ページに対応しなければならないことを示しています。


目次 索引

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