以下、図面を参照して、実施形態について詳細に説明する。
図1は、実施形態に係る画像形成装置10の概略構成を示すブロック図である。画像形成装置10は、CPU(Central Processing Unit)12、RAM(Random Access Memory)14、例えばフラッシュメモリ等からなる不揮発性の記憶部16、I/O(入出力)ポート18、通信インタフェース20を備え、それらはバス22を介して相互に接続されている。
IOポート18には、LCD等から成る表示部及びテンキーやタッチパネル等から成り利用者による操作を受付ける操作受付部が設けられた操作パネル24、HDD(ハードディスクドライブ)26、及び入力された画像データが表す画像を記録媒体上に形成する画像形成部28が接続されている。
また、通信インタフェース20は、通信回線やLAN等のネットワークに接続されている。画像形成装置10は、通信インタフェース20を介して、該ネットワークに接続された他の端末と相互に情報をやりとりする。
CPU12は、記憶部16に記憶されたプログラムを実行する。なお、CPU12が実行するプログラムが記憶される記録媒体は、記憶部16に限定されず、例えば、HDD26であってもよいし、CD−ROMであってもよいし、図示は省略するが、DVDディスク、光磁気ディスク、ICカードなどの可搬型記録媒体や画像形成装置10の外部に備えられたHDD等の記憶装置等であってもよく、更にまたネットワークを介して接続されたデータベース、或いは他のコンピュータシステム並びにそのデータベースであってもよい。また、RAM14は、プログラム実行時のワークメモリ等として利用される。
記憶部16には、画像形成装置10の利用者に対して画像形成装置10の様々な機能を提供する処理を行うアプリケーションのプログラムと、アプリケーションのプログラムを実行するためのプラットフォームとして機能するオペレーティングシステム(OS)のプログラムが各々記憶されている。このOSは、仮想アドレス機構が導入され、仮想アドレスを使用するOSであって、例えば、Linux(登録商標)であってもよい。
更に又、記憶部16には、あるOS上で動作させるために作成されたプログラムを、他のOS上で動作するように実装する(以下、移植という)ために事前に作成された拡張モジュールのプログラムも記憶されている。本実施形態では、移植元のOS(上記「あるOS」に相当)が、仮想アドレスを使用しない(仮想アドレス機構を有さない)リアルタイムOSであり、移植先のOS(上記「他のOS」に相当)が、上記仮想アドレスを使用するOSである場合を例に挙げて説明する。
なお、拡張モジュールは、事前に移植対象プログラムとリンクされた状態で、記憶部16に記憶されている。本実施形態では、拡張モジュールと移植対象プログラムとがリンクされて生成されたモジュールを、ロードモジュールと称する。本実施形態では、ロードモジュールに含まれる拡張モジュールとOSの機能とを用いて、移植対象プログラム自体を変更することなく、移植前の仮想アドレスを使用しない動作環境から、仮想アドレスを使用する動作環境に移植させるようにしている。
ここで、プログラムの移植に係る背景について、より詳細に説明する。組込ソフトウェアの高機能化に伴い、Linux(登録商標)などの高機能なOSを用いて組込ソフトウェアを開発する必要が生じている。既存の組込ソフトウェアは既に大規模化しており、既存ソフトウェアと同等の機能を高機能なOSに対応するように新規に開発することは困難である。従って、既存のソフトウェアを、高機能なOS上に移植する必要性がある。
従来の組込ソフトウェアは、仮想アドレスを使用しない(仮想アドレス機構を有さない)リアルタイムOS上で動作するように実装され、アドレス値を用いてメモリやIOポート等のハードウェア資源(以下、リソースという)を直接アクセスするように実装されている場合が多い。即ち、リソースを指定するためのアドレス値を固定したプログラミングをしているソフトウェアが多く存在していた。ここでアドレス値を固定したプログラミングとは、アドレス値を数値等の固定値で記述したり、アドレス値を固定値で記述した領域への参照を使用するなど、直接または間接的に固定したアドレスを利用したプログラミングである。リアルタイムOSでは、アドレス値を直接的に物理アドレスと対応させて使用するため、メモリやIOポート等のリソースを、プログラムコードに含まれるアドレス値を用いて直接アクセスすることが可能であるためである。
一方、高機能OSには、仮想アドレスを使用するためのメモリ管理機構が導入され、プログラムはユーザプロセス毎に独立したメモリ空間で、仮想アドレスを用いて動作する。従って、プログラムがアドレス値を用いてアクセスした場合、仮想アドレスでのアクセスとして扱われる。OSは、その仮想アドレスを物理アドレスに対応付ける変換表(ページテーブル)を事前に設定しておく(以降、この設定をマップと称する)。CPUは、ページテーブルに基づいて仮想アドレスを物理アドレスに変換することで、メモリやIOポートにアクセスする。ページテーブルは、RAM14や記憶部16に記憶される。
物理アドレスを、利用可能な(即ち使用済でない)仮想アドレスにマップする機能として、例えば、Linux(登録商標)などUnix(登録商標)系のOSでは、mmap()システムコールというマップ機能(関数)が用意されている。一般的には、このマップ機能によりOSが用意した仮想アドレスが使用される。このため、従来の環境下で直接的に物理アドレスに対応するものとして固定値のアドレス値が実装されたプログラムを実行したとしても、そのアドレス値をそのまま用いてリソースにアクセスすることはできない。
更に、プログラムに実装されたアドレス値が任意の仮想アドレスに割り当てられるように上記マップ機能を拡張したとしても、割り当てられたアドレスが、プログラムの実行時に使用される仮想アドレスの領域、例えば、プログラムのコード、データ、及び一時データが展開される領域や、マップ機能で割当済の領域、スタックなどに割り当てられた領域等と重複してしまう可能性がある。
そこで、仮想アドレスを使用しないOS上で動作するように作成されたプログラムを、仮想アドレスを使用するOS上で動作させるためには、そのプログラムに固定値で指定されたアドレス値を、利用可能な(プログラム実行時に使用されない)仮想アドレスとなるようにソースコードを変更する手法が考えられる。
しかしながら、そのようなプログラムは、その実装も古く規模も大きく複雑である場合も多く、プログラム中に分散する多くの依存箇所(アドレス値)を特定し、ソースコードを変更することは困難である。例えば、画像メモリに依存した画像ライブラリなどの場合、アドレス値に依存するコード量が多く、ソースコードの変更が困難となる。
そこで、ソースコードに分散するアドレス値の各々を変更しなくても、仮想アドレスを使用するOS上で動作可能となるように、本実施形態の画像形成装置10に、以下に説明するアドレス管理装置を実装した。ここで、アドレス管理装置は、画像形成装置10のCPU12が記憶部16に記憶されたプログラム(ここでは、移植対象プログラム本体を除く)実行することにより実現される機能により構成される。
図2は、画像形成装置10に実装されたアドレス管理装置の機能構成を示す図である。
<ロードモジュール>
ロードモジュール50は、前述したように、移植対象プログラム52と拡張モジュール54とがリンクされたモジュールである。拡張モジュール54は、移植する際に、移植対象プログラム52に対して追加的に付与されたプログラムであるため、移植対象プログラム52及び拡張モジュール54は、ロードモジュール50として一体的に扱われるが、拡張モジュール54は移植対象プログラム52をOS32上で正常に動作させるために使用されるモジュールであって、移植対象プログラムとは実行開始タイミング等も異なることから、以下では移植対象プログラム本体としての移植対象プログラム52と、追加的な拡張モジュール54とを区別して説明する。
移植対象プログラム52には、リソース(RAM14等のメモリやIOポート18等)をアクセスするための(すなわち、リソースを指定するための)アドレス値が、移植元の物理空間の物理アドレス値に依存して記述されている依存部分と、該アドレス値が上記物理アドレス値に依存せずに記述されている非依存部分とがある。より具体的には、前者の場合には、リソースを指定するためのアドレス値が即値で(前述したように、数字等の固定値で直接的或いは間接的に)プログラムコードに記述されている。後者の場合には、該アドレス値が固定値を記述しない形式でプログラムコードに記述されており、例えば、プログラムをコンパイルする際などにアドレスが解決される(すなわち、アドレス値は可変)。以下、前者の、物理アドレス値に依存して固定値がプログラムに記述されたアドレス値を依存アドレス値と呼称し、後者の非依存アドレス値と区別して説明する。
拡張モジュール54は、移植対象プログラム52の補助的な機能を有し、移植対象プログラム52の情報を提供するプログラムである。拡張モジュール54は、以下の3つの機能を有する。
(1)移植対象プログラムに含まれる依存アドレス値の範囲を示す情報を保持する。後述するローダ38がこの値を参照し、この値の範囲が、移植対象プログラム52を含むロードモジュール50の実行時の仮想アドレスの領域と重畳しているか否かを判断する際に使用する。
(2)リソースの物理アドレスを取得する。拡張モジュール54は、移植先環境でのリソースの物理アドレスを、デバイスドライバ36を介して参照する。
(3)取得したリソースの物理アドレスを、(1)の依存アドレスが仮想アドレスとなるようにマップする(ページテーブルを設定する)。マップ処理は、デバイスドライバ36を介して実行される。
なお、拡張モジュール54を設ける代わりに、移植対象プログラム52を変更し、拡張モジュール54の機能及び拡張モジュール54が保持する情報を、移植対象プログラム52に保持させてもよい。このように移植対象プログラム52を変更する場合には、拡張モジュール54なしで、ロードモジュールが構成される。なお、このように移植対象プログラム52を変更したとしても、拡張モジュール54のコードを移植対象プログラム52のコードに追加するだけであるため、拡張モジュール54を移植対象プログラム52にリンクさせる場合と同様の作業は発生するものの、移植対象プログラム52のコードに分散された依存アドレス値を変更するほどの手間はかからない。
<移植先環境>
図2において、移植先環境30が、仮想アドレスを使用するOS32と、当該OS32が物理空間として管理するハードウェア40とで表わされている。また、図2では、画像形成装置10に装備された様々なハードウェアを総称して、「ハードウェア40」として図示した。OS32は、カーネル34、デバイスドライバ36、及びローダ38を含んで構成される。
デバイスドライバ36は、OS32の機能の1つとして動作する。本実施形態では、デバイスドライバ36は、以下の3つの機能を有する。
(1)物理アドレス空間に、移植対象プログラム52が利用するリソースを割り当てる。具体的には、ハードウェア40のレジスタアドレスを割り当てる処理を行う。これは、カーネル34に対してレジスタアドレスを登録することにより行なわれる。
(2)割り当てたリソースの物理アドレスを、拡張モジュール54に提供する。
(3)拡張モジュール54からのマップ要求に応じて、仮想アドレスをマップする。即ち、移植対象プログラム52の依存アドレスが仮想アドレスとして扱われるように、割り当てた物理アドレスと依存アドレスとが対応付けられたページテーブルを設定する。この設定処理の一部を、OS32の元々の機能として備わっていた機構の一部を利用することにより実行してもよい。また、機能や使用するリソース毎に、別々のデバイスドライバで実現しても良い。更に又、他のデバイスドライバ、又は他のOSが提供するマップ機構を用いて仮想アドレスを割り当てても良い。
なお、拡張モジュール54とデバイスドライバ36との機能分担は変更可能である。例えば、拡張モジュール54が物理アドレスを参照し、拡張モジュール54が、依存アドレスが仮想アドレスとして扱われるようにデバイスドライバ36に指示し、デバイスドライバ36が事前に割り当てた物理アドレスを当該指示された仮想アドレスにマップするようにしても良い。
ローダ38は、OS32の機能の1つとして動作する。画像形成部28は、ロードモジュール50を仮想空間上にロードして実行する。ここでは、ローダ38は、OS32の仮想空間のメモリ上に、ロードモジュール50を実行するときに使用される仮想アドレス(以下、実行時仮想アドレスという)の領域を設定する。実行時仮想アドレスの領域には、例えば、OS32をLinux(登録商標)とした場合、テキスト(text)領域、初期値ありデータ(data)領域、初期値なしデータ(bss)領域、ヒープ(heap)領域、ダイナミックリンクライブラリ(mmap)領域、及びユーザスタック(user stack)領域が含まれる。ローダ38は、これら領域を設定して配置する。text領域には、プログラムの命令列が展開される。data領域には初期値付きの変数が展開される。bss領域には、初期値なしの変数が展開される。heap領域及びmmap領域は、作業用メモリ領域であって、何れもmalloc()ラッパ関数で作業用メモリとして割り当てられる領域である。また、mmap領域は、mmap()システムコールにおいてファイルや物理メモリにマップされる領域である。user stack領域は、一時的に待避させるデータ等が格納される。なお、text領域、data領域、bss領域は、連続した領域として配置されるものとして規定されることから、以下では、text領域、data領域、及びbss領域をまとめて、text/data/bss領域と称する。
なお、ローダ38は、依存アドレスが、実行時仮想アドレス空間と重畳している場合、即ち、使用する(可能性がある)仮想アドレスに同一の部分が存在する場合、実行時仮想アドレス空間の配置を変更する。
次に、本実施形態の作用を図3、図4を参照して説明する。図3は、本実施形態のアドレス管理装置により行なわれる処理の流れを示すフローチャートである。なお、図2において、動作の主体と動作の作用対象とを矢印で結び、図3のステップ番号を図2の対応する矢印の近傍に付して、各ステップの動作の手段を明示した。また、図4は、アドレス空間の配置を模式的に示した図である。0x14000000〜0x1C000000に存在する128MBのビットマップメモリに対して、この範囲のアドレスを即値でアクセスして画像処理を実行するプログラムを移植対象プログラム52として移植する場合において、text/data/bss領域の仮想アドレスと依存アドレス値とが重複する例が示されている。
図4(A)は、移植元の物理アドレス空間で移植対象プログラム52が使用するアドレス値(依存アドレス値)の範囲例を示す図であり、図4(B)の(1)及び(2)は、移植先の仮想アドレス空間の後述する実行時アドレス配置例を示し、図4(B)の(3)は、移植先における物理アドレス空間のリソースの物理アドレス値の範囲例を示す図である。
なお、ここでは、移植対象プログラム52及び拡張モジュール54は事前にコンパイルされ、ロードモジュール50としてリンクされているものとする。リンクの方法は、再配置可能、すなわちロードの際に仮想アドレスを解決する方法と、OS32で決められた仮想アドレスが静的に割り当てられる方法とがあるが、何れを採用してもよい。
図3のステップS01において、デバイスドライバ36は、物理アドレス空間に移植対象プログラム52が利用するリソース(RAM14やIOポート18など)を割り当てる(図4(B)の(3)も参照)。例えば、カーネル34に登録することで、128MBの物理メモリのアドレス空間を割り当てる。なお、カーネル34のブート処理により、ブートメモリとして割り当てても良いし、カーネル34起動の際に、memパラメータを指定してカーネル34が認識するメモリを搭載されているメモリよりも少なく設定し、カーネル34が認識しないメモリ領域を使用するようにしても良い。
また、例えば、下記ステップS02を先に行ない、下記ステップS02で取得された依存アドレス値の範囲の前後にマージンを持たせたときのサイズに対応させてリソースを割り当てるようにしても良い。その際、アラインメントを考慮して割り当てるようにしても良い。例えば、OS32は、物理アドレス空間及び仮想アドレス空間を、基本的に予め定められたサイズのページと呼ばれる単位に分割してメモリ管理を行うが、上記物理アドレス空間にリソースを割り当てる際、当該リソースの物理アドレス空間における開始アドレスが、OS32のページメモリの単位(4K、2Mなど)の倍数になるようにする。
また、リソース割当の別の例として、ハードウェア40のレジスタやビデオメモリなどの物理アドレスを取得し、カーネル34に登録する場合などがある。
次に、ステップS02において、ローダ38は、移植対象プログラム52が内部で使用している依存アドレス値の範囲を取得する(図4(A)も参照)。この値は、予めロードモジュール50の拡張モジュール54内のコードの識別可能なセクション中に格納しておく。例えば、ELF形式のセクションヘッダにアドレス値とその範囲の情報を格納しておくことができる。ローダ38は、当該セクションを読出すことで、依存アドレス値の範囲を取得する。なお、移植対象プログラム52及び拡張モジュール54を含むロードモジュール50は、この時点では起動されていない。
このように、拡張モジュール54に依存アドレス値の範囲を示す情報を保持させておき、移植対象プログラム52とリンクしたロードモジュール50として構成することで、移植対象プログラム52本体は変更不要となる。依存アドレス値の範囲を示す情報としては、例えば、開始及び終了アドレスを格納するか、或いは開始アドレスとサイズ(バイト数)を格納する。
なお、依存アドレス値の範囲を示す情報を、拡張モジュール54とは別に設定ファイルに記述して、記憶部16等に記憶しておくなど、他の方法を用いても良い。
ステップS03において、ローダ38は、ロードモジュール50の実行時仮想アドレス空間の情報を取得する(図4(B)の(1)も参照)。具体的には、ローダ38は、ロードモジュール50のオブジェクトファイルを解析し、ロードモジュール50のプログラムのコード及びデータが記憶される領域(前述したtext/data/bss領域)の各領域や、heap領域、mmap領域、及びuser stack領域の各領域のサイズ(容量)を取得する。なお、各領域の仮想アドレス空間における開始アドレスは、OS32に応じて予め規定値が定められているため、この値を取得する。また、各領域のサイズは、使用量が可変であるので、その最大値を各領域のサイズとして取得するものとする。
例えば、Linux(登録商標)のx86シリーズの32ビット版の場合の規定値では、text/data/bss、heap、mmap、及びuser stackの各領域の仮想アドレス空間上での開始アドレスは、各々、0x10000000、bss領域の直後、0x80000000、0xC0000000である。ここで、user stack領域は、開始アドレスから前方(アドレス値の小さい方向)に使用される。また、0xC0000000以降は、カーネル34により利用される仮想アドレスの範囲とされる。
次に、ステップS04において、ローダ38は、依存アドレス値の範囲と、実行時仮想アドレスの範囲とで重複している部分があるか否かを判断する。例えば、依存アドレス値の範囲が0x14000000〜0x1C000000で、text/data/bss領域のサイズが512MBとすると、上記開始アドレスの規定値から、その仮想アドレスの範囲は、0x10000000〜0x30000000となるため、依存アドレス値の範囲は、text/data/bss領域に含まれることになる。この場合には、重複していると判断される(図4(A)及び図4(B)の(1)も参照)。
ローダ38は、依存アドレス値の範囲と、実行時仮想アドレスの範囲とで重複している部分があると判断した場合には(ステップS05、Yes)、ステップS06において、ローダ38は、ロードモジュール50の実行時仮想アドレスが、依存アドレス値の範囲と重複しないように、ロードモジュール50の実行時仮想アドレスの配置を決定する。
この時、仮想アドレス空間を予め定められた単位に区切り、区切られた各セグメントのうち、依存アドレス値を含まないセグメントに、実行時仮想アドレスが配置されるように実行時仮想アドレスの各領域のアドレスを決定する。
ここで、各セグメントの単位は任意に設定可能である。図4(B)の(2)に、1GBを単位とし、先頭の1GBに依存アドレス値の範囲が存在するため、先頭の1GBには、ロードモジュール50の実行時仮想アドレスの各領域を配置しないようにした例を示す。1バイト以上の任意の単位で重複が回避されるように配置処理することが可能である。
また、この処理は一般に箱詰め問題(bin packing problem)と呼ばれる分野のうち、1次元の箱詰め問題(One-dimensional bin packing problem)のアルゴリズムを応用することが可能である。
ステップS07において、ローダ38は、上記決定した配置に従って、ロードモジュール50の実行時仮想アドレスを再配置する。静的にリンクされているロードモジュール50の場合には、ステップS06の決定結果に基づき、ロードモジュール50のオブジェクトファイル中に埋め込まれている実行時仮想アドレスを変更する。元のロードモジュール50のファイルを直接変更するのではなく、一時ファイルやメモリ上に読み出した状態で変更する。この処理は次のステップS08で示したロードの処理中に、逐次的に実行するようにしても良い。
また、再配置可能にリンクされているロードモジュール50の場合には、ロード時のアドレス解決の際に、ステップS06の決定結果に基づき、アドレスを設定しながらロードしても良い。
ここで、変更/解決されるアドレスは、ロードモジュール50に含まれる変数や関数のアドレスであり、変数に格納されたアドレスは対象にならない。リソースは、元々ロードモジュール50の外部にあり、ポインタ変数内に、そのリソースのアドレスが事前に格納されるか、或いは実行の際に格納されるので、変更/解決の対象にはならない。
ステップS08において、ローダ38は、上記決定した実行時仮想アドレスの領域にロードモジュール50をロードし、ロードモジュール50中の拡張モジュール54の実行を開始する。ここでは、まだ移植対象プログラム本体(移植対象プログラム52)の実行は開始されない。
ローダ38は、ロードモジュール50のタスク管理テーブルを生成し、上記決定された実行時仮想アドレスの配置に従い、ページテーブルを設定することで、ロードモジュール50の仮想アドレス空間を生成する。その他、引数、環境変数、ファイル管理、及びマウントポイント等、プログラムの実行に必要な種々の資源を割りあて、OS32のスケジューラの実行キューに追加する。
ステップS09において、拡張モジュール54は、デバイスドライバ36を呼び出して、ステップS01で割り当てたリソースの物理アドレス及びサイズの情報を取得する。なお、ロードモジュール50の起動パラメータや設定ファイルに当該リソースの物理アドレス及びサイズの情報を記述しておき、ロードモジュール50から上記情報を取得するようにしても良い。
ステップS10において、拡張モジュール54は、デバイスドライバ36を呼び出して、デバイスドライバ36に、移植先におけるリソースの物理アドレスを、移植対象プログラム52の依存アドレス値にマップさせる。デバイスドライバ36は、拡張モジュール54からの要求に応じて、依存アドレス値を仮想アドレスとして、リソースを参照するためのページテーブルを設定することにより、当該依存アドレス値をリソースの物理アドレスにマップする。
例えば、Linux(登録商標)等のUnix(登録商標)系のOSでは、mmap()システムコールが用意されているので、拡張モジュール54が、これを利用可能である。mmap()システムコールは、以下のように表わされる。
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
ここで、第1引数には、割り当てたい仮想アドレス、即ち、プログラムの依存アドレスの範囲の先頭アドレスを指定する。第2引数には、依存アドレス値の範囲の長さを指定する。第6引数には、ステップS01で割り当てた物理アドレスを指定する。第5引数には、後述するデバイスドライバ36をオープンして得たファイル記述子を指定する。第3引数には、PROT_READ及びROT_WRITEのフラグを指定する。第4引数には、MAP_FIXEDを指定する。また、マップした領域をプロセス間で共有する場合は、MAP_SHAREDフラグを併せて指定しても良い。
ここで、デバイスドライバ36には、mmap()システムコールに対応して呼び出されるmmapメソッドが用意されており、その中で、デバイスドライバ36は、指定された仮想アドレスに対して、仮想アドレス機構で使用するページテーブルを設定する。また、OS32で使用する他の管理情報も併せて設定する。OS32がLinux(登録商標)の場合には、使用済の仮想アドレスの範囲を管理するvmarea構造体を設定する。また、OS32が用意しているサービスルーチンを利用して、これらの処理を実行しても良い。OS32がLinux(登録商標)の場合には、OS32のサービス関数remap_pfn_range()が利用可能である。
ステップS11において、拡張モジュール54は、移植対象プログラム52を呼び出して、移植対象プログラム52の実行を開始する。
一方、ステップS05において、重複する部分はないと判断された場合には、ステップS12において、実行時仮想アドレスの配置はそのままとされ、ステップS08に進み、上記説明した処理が行なわれる。
以上説明したように、本実施形態のアドレス管理装置によれば、移植元ハードウェアのリソース(メモリ、IOポート等)の物理アドレス値に依存して実装されたプログラムを、実装変更する(すなわち、移植対象プログラム本体のコードに記述されたアドレス値の各々を変更する)ことなしに、移植先仮想アドレス空間で実行することができる。
なお、前述したように、拡張モジュール54を設ける代わりに、移植対象プログラム52を変更し、拡張モジュール54の機能及び拡張モジュール54が保持する情報を、移植対象プログラム52に保持させて移植させる場合には、移植対象プログラム52の本体のプログラムではなく、上記拡張モジュール54が行うステップは、移植対象プログラム52の拡張モジュール54の機能に相当する部分が担い、移植対象プログラム52の本体部分の実行は、ステップS11において開始される。
アドレス管理装置の構成及び作用は、上記説明した例に限定されない。以下、アドレス管理装置の様々な変形例について説明する。
(1)アラインメントの制御
ステップS06で重複を回避する際に、アラインメントを考慮し依存アドレス値の範囲の前後に余裕を持たせた状態で再配置を決定してもよい。例えば、実際の依存アドレス値の範囲の開始又は終了が4Kバイトの倍数でなかった場合、各々、開始アドレスを前方に、終了アドレスを後方に拡大し、4Kバイトの倍数となるように扱っても良い。
(2)セグメントの細分化
前述したステップS06において、1GB単位のセグメントに分割し、これを配置単位として重複を回避する例を示した。しかしながらこの場合、1GBの境界を跨ぐ領域に依存アドレス値の範囲が存在すると、全4Gバイトの仮想アドレス空間の場合、残り2セグメントとなり、text/data/bss領域、heap,mmap領域、user stack領域の複数の領域を残りの各セグメントに配置できなくなってしまう。これを回避するため、予めセグメントの単位(配置単位)を小さく設定しておくようにしてもよい。
また、依存アドレス値の範囲のサイズに応じて、配置単位を決定するようにしても良い。例えば、80MBを最小単位とし、2MBの倍数を単位として配置する場合において、依存アドレス値の範囲のサイズが200MBとすると、それより大きい256MBのセグメントサイズを1単位として再配置が決定されるようにする。
また、最初は、配置単位のサイズを大きく設定しておき、配置が失敗した場合には、配置単位を当該配置が失敗したときのサイズより小さなサイズとして、再配置を試みるようにしてもよい。それでも、なお配置が失敗した場合には、更に小さなサイズを配置単位おして再配置を試みる。例えば、配置単位を1GBから、2分の1ずつ徐々に小さくしていき、配置が成功するまで繰り返すようにしても良い。
(3)ロードモジュール実行時仮想アドレスに含まれる領域のサイズ変更
ロードモジュール50の実行時仮想アドレスに含まれる領域の一部のサイズを変更する方法を取ることも可能である。例えば、heap領域やmmap領域などの作業用メモリ領域の仮想アドレスを制限する方法である。作業用メモリ領域と依存アドレス値の範囲とで、重複する部分がある場合には、heap領域又はmmap領域の仮想アドレス空間上の開始アドレス及び終了アドレスの一方又は両方を変更することによって、依存アドレス値の範囲と重畳しないように制御することが可能である。
また、依存アドレス値の範囲が、user stack領域の仮想アドレスと重複した場合も同様に、user stack領域の開始アドレス、又は使用サイズの上限を変更するように制御しても良い。
(4)他の重複回避方法
ロードモジュールの実行時仮想アドレスの領域の一部を分割するようにしても良い。例えば、依存アドレス値の範囲が、text領域及びdata領域と重畳する場合、依存アドレス値の範囲を避けるように、text/data領域を依存アドレス値の範囲の前後に分割して配置するようにしても良い。例えば、text領域を依存アドレス値の範囲の先頭アドレスより手前に配置し、data領域を依存アドレス値の範囲の最終アドレスより後ろに配置する。その際、text領域及びdataの領域を、依存アドレス値の範囲に隣接するように配置しても良い。
また、依存アドレス値の範囲がmmap領域と重複する場合、依存アドレス値の範囲がマップ済み、即ち使用済の仮想アドレスとして割り当てるようしても良い。mmap領域は、mmap()システムコールを使用して確保される領域であるので、リソースのマップも、mmap領域の一部として扱われるようにすることができる。すなわち、本来のmmap領域として使用される領域を小さくする。
同様に、依存アドレス値の範囲が、heap領域、或いはuser stack領域と重複する場合についても、同様に、依存アドレス値の範囲が、割当済のheap領域、user stack領域として扱われるようにしても良い。すなわち、本来のheap領域或いはuser stack領域として使用される領域を小さくする。
この場合、これらの領域は、スワップの対象外の領域となるので、そのようにメモリ管理上の制御を施すように設定する。OS32がUnix(登録商標)系のOSの場合には、予め定められた拡張モジュールでLockシステムコールを用いるか、デバイスドライバ36で同様の処理を実行すれば良い。また、例えば、OS32がLinux(登録商標)の場合には、デバイスドライバ36でこれらの領域のページメモリ用管理フラグを予約済み(RESERVED)にセットすることにより、カーネル34のコード領域と同様にスワップの対象外とすることが可能である。
また、依存アドレス値の範囲がtext/data領域と重畳する場合、拡張モジュール中に、依存アドレスの範囲を含む埋草(パディング)のセクション、即ち機能上は使用しないダミーの領域を当該重複する部分に対応する位置に確保しておくこともできる。このダミー領域の仮想アドレスは、ステップS10のマップの際に、依存アドレス値として扱われるように上書きするようにしても良い。これにより、ロードモジュール50の実行時仮想アドレスを変更する手順が省略される。
(5)リンカによる実現
上記例では、ローダ38によって実行時仮想アドレスの配置の変更を実現する方法を示したが、図5に示すように、移植対象プログラム52及び拡張モジュール54のリンクを実行するリンカ60を用いて実現しても良い。具体的には、上記ステップS02〜S06の処理を実行するツール(アドレス管理ツール62)を用意し、そのアドレス管理ツール62から、ステップS06で決定した変更後の実行時仮想アドレスの配置情報をリンクパラメータとして出力する。ステップS07において、リンカ60が、上記リンクパラメータを用いて、移植対象プログラム52及び拡張モジュール54をリンクしたロードモジュール50を生成するようにしても良い。これにより、リンクパラメータにより実行時仮想アドレスが埋め込まれたロードモジュール50が生成される。
(6)拡張モジュールの実装方法
上記では、拡張モジュール54を、移植対象プログラム52とリンクされるコンパイルユニットとして実現する方法を説明したが、これに限定されず、例えば、前述したように、拡張モジュール54の機能を移植対象プログラムに組み込んでも良い。この場合、移植対象プログラム52のプログラムコードにおいて、移植対象プログラム52の初期化処理を実行する部分に、拡張モジュール54が行う処理の記述を追加すれば良い。また、拡張モジュール54を移植対象プログラム52とリンクせず、独立したモジュールとして実現しても良い。例えば、共有ライブラリとして実現し、移植対象プログラム52の初期化処理で拡張モジュール54が提供する機能を呼び出すようにしても良い。
以上の例では、仮想アドレスを使用しないOSから仮想アドレスを使用するOSへの移植を例に説明したが、移植元のOSが仮想アドレスを使用するOSであって、移植対象のプログラムが、移植元のOSの仮想アドレス値に依存して実装されている場合であっても、上記と同様に処理することで移植時の問題を解決可能である。即ち、依存アドレスを移植先のリソースにマップし、依存アドレスが実行時仮想アドレス空間と重複する場合は実行時仮想アドレスが依存アドレスと重複しないように配置を変更すれば良い。