前へ | 次へ | 目次 | 索引 |
表 5-2 に示したランタイム・ライブラリ・ルーチンは,メモリ・ページを割り当てるか,または解放します。互換性を維持するために,これらのルーチンでは,ユーザが指定したページ・カウント情報をページレットの値として解釈します。
ルーチン | 引き数 | Alphaシステムでの解釈 |
---|---|---|
LIB$GET_VM_PAGE | number-of-pages 割り当てる連続ページのページ数を指定する。 |
ページレット単位の値として解釈され,CPU固有のページに切り上げられるか,または切り捨てられる。 |
LIB$FREE_VM_PAGE | number-of-pages 割り当てを解除する連続ページのページ数を指定する。 |
ページレット単位の値として解釈され,CPU固有のページになるように切り上げられるか,または切り捨てられる。 |
アプリケーションが実行するメモリ割り当てを変更しなければならないかどうかを判断するには,メモリがどこで割り当てられるかを確認しなければなりません。メモリ割り当てを実行するシステム・サービス・ルーチン($EXPREGと$CRETVA)を使用すれば,次の2種類の方法でメモリを割り当てることができます。
Alphaアーキテクチャでは,VAXアーキテクチャと同じ仮想アドレス空間レイアウトを定義しており,VAXシステムの場合と同じ方向にP0領域とP1領域を拡大できます。 図 5-1 はこのレイアウトを示しています。
図 5-1 仮想アドレスのレイアウト
アプリケーションで$EXPREGシステム・サービスを使用して仮想アドレス空間を拡張することによりメモリを割り当てる場合には,ソース・コードを変更する必要はありません。これは,VAXシステムで引数として指定した値がAlphaシステムでも正しく動作するからです。この理由は次のとおりです。
ただし,システム・サービスはページ・カウントをCPU固有のページに切り上げるため,アプリケーションに対してシステムが実際に割り当てるメモリ・サイズは,VAXシステムの場合よりAlphaシステムの場合の方が大きくなる可能性があります。割り当てられたメモリ全体はアプリケーションで使用できます。アプリケーションは通常,必要なバッファを確保するためにメモリを割り当てます。しかし,バッファのサイズは各プラットフォームで変化しないため,指定した値はアプリケーションの必要条件を満足できます。
アプリケーションを変更する必要はありません。しかし,$EXPREGシステム・サービスが戻すメモリ・サイズは,Alphaアーキテクチャを実現した各システムで異なる可能性があるため,システムが割り当てた正確なメモリ境界を確認しておくことが適切でしょう。正確なメモリ境界を確認するには,$EXPREGシステム・サービスに対して省略可能な引数である retadr 引数を指定します(アプリケーションでこの引数がまだ指定されていない場合)。retadr 引数には,システム・サービスが割り当てたメモリの先頭アドレスと末尾アドレスが格納されます。
たとえば,例 5-1 のプログラムは,$EXPREGシステム・サービスを呼び出すことにより10ページの追加メモリを要求します。このプログラムを VAXシステムで実行した場合には,$EXPREGシステム・サービスは5120バイトの追加メモリを割り当てます。このプログラムをAlphaシステムで実行した場合には,$EXPREGシステム・サービスは少なくとも8192バイトを割り当てます。また,Alpha アーキテクチャの特定の動作のページ・サイズによっては,それ以上のサイズのメモリを割り当てることもあります。
例 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 に示した番号に対応します。
アプリケーションで$CRETVAシステム・サービスを使用することにより,仮想アドレス空間内のメモリを再割り当てする場合には,$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); } } |
$EXPREGシステム・サービスと$CRETVAシステム・サービスによって割り当てたメモリを解除するために$DELTVAシステム・サービスを呼び出す場合,$DELTVAシステム・サービスに対して inadr 引数として,retadr 引数に戻されたアドレス範囲(メモリを割り当てるために使用したルーチンから戻された値)をアプリケーションで使用しているときは,アプリケーションを変更する必要はありません。実際に割り当てられるサイズは各システムで異なるため,割り当ての範囲に関してアプリケーションで何らかの仮定を設定することは望ましくありません。
5.3 メモリ・マッピング・ルーチンの確認
アプリケーションで実行するメモリ・マッピングを変更しなければならないかどうかを判断するには,アプリケーションが仮想メモリのどの部分でマッピングを実行するかを確認しなければなりません。メモリ・マッピング・システム・サービス($CRMPSCと $MGBLSC)を使用すれば,次の方法でメモリをマッピングできます。
アプリケーションがセクションをマッピングする方法は,おもに $CRMPSCシステム・サービスと$MGBLSCシステム・サービスに対する次の引数によって決定されます。
$CRMPSCシステム・サービスと$MGBLSCシステム・サービスは少なくともCPU固有のページを1ページ分マッピングします。セクション・ファイルが1ページ未満の場合には,ページの残りの部分には0が格納されます。ページの残された空間をアプリケーションで使用すべきではありません。なぜなら,セクション・ファイルに格納できるデータだけがディスクに書き戻されるからです。
5.3.1 拡張した仮想アドレス空間へのマッピング
アプリケーションでアプリケーションの仮想アドレス空間の拡張領域にセクション・ファイルをマッピングする場合には,ソース・コードを変更する必要はありません。これは,拡張された仮想アドレス空間にマッピングされるため,たとえAlphaシステムで割り当てられるメモリのサイズがVAXシステムより大きくても,既存のデータの上にマッピングされる危険性がないからです。このように,VAXシステムで$CRMPSC システム・サービスに対して引数として指定した値は,Alphaシステムでも正しく機能します。
セクションを仮想メモリの拡張領域にマッピングするアプリケーションは,変更しなくても正しく動作できますが,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 ); } } |
アプリケーションでセクション・ファイルを1ページのメモリにマッピングする場合には,Alphaシステムの$CRMPSCおよび$MGBLSCシステム・サービスでこの操作モードがサポートされないため,ソース・コードを変更しなければなりません。Alphaシステムのページ・サイズはVAXシステムのページ・サイズと異なっており,さらに Alpha アーキテクチャの各実装ごとに異なるため,アプリケーションでセクション・ファイルをマッピングするために正確なメモリ境界を指定しなければなりません。このような使い方をした場合,$CRMPSCシステム・サービスは,引数が誤っていることを示すエラー(SS$_INVARG)を戻します。
アプリケーションでこのモードを使用しているかどうかを判断するには,inadr 引数に指定した先頭アドレスと末尾アドレスを確認します。両方のアドレスが同じであり,同時に,flags 引数の SEC$M_EXPREGビットがセットされていない場合には,アプリケーションはこのモードを使用しています。
このモードの$CRMPSCシステム・サービスの呼び出しを変更する場合には,次のガイドラインに従ってください。
前へ | 次へ | 目次 | 索引 |