この章では、T-Kernel/SM(System Manager)で提供している機能の詳細について説明を行う。
全般的な注意・補足事項 | |
---|---|
|
システムメモリ管理機能は、T-Kernelが動的に割り当てるすべてのメモリ(システムメモリ)を管理するための機能である。T-Kernel内部で使用しているメモリやタスクのスタック、メッセージバッファ、メモリプールなどもここから割り当てる。
システムメモリは、ブロック単位で管理される。ブロックサイズは、通常MMUで定義されるページサイズであり、現在の実装では4KB程度を想定している。MMUを使用しないシステムでは任意のサイズでよいが、MMUのページサイズと同程度を推奨する。ブロックサイズは、tk_ref_smb により取得できる。
システムメモリは、共有空間のメモリである。T-Kernelではタスク固有空間のメモリの管理は行わない。
システムメモリ管理機能は、システムメモリからのメモリの割当てや解放をブロック単位で行うシステムメモリ操作用の拡張SVCと、ブロック単位で確保されたシステムメモリをさらに細分化して管理するメモリ割当てライブラリからなる。
システムメモリ管理機能は、T-Kernel内部で利用する他、アプリケーションやサブシステム、デバイスドライバなどからも利用可能である。なお、T-Kernel内部での利用は拡張SVCを経由しない方法でもよく、実装定義とする。
システムメモリ割当ての機能では、システムメモリからのメモリの割当て、解放と、システムメモリ情報を参照する機能を拡張SVCで提供する。
nblk
で指定したブロック数分の連続したメモリ領域を attr
で指定した属性で割り当てる。割り当てたメモリの先頭アドレスを addr
に返す。
attr
では、以下の属性を指定する。
attr := (TA_RNG0 || TA_RNG1 || TA_RNG2 || TA_RNG3) | [TA_NORESIDENT]
TA_RNG0 | 保護レベル0のメモリを指定する |
TA_RNG1 | 保護レベル1のメモリを指定する |
TA_RNG2 | 保護レベル2のメモリを指定する |
TA_RNG3 | 保護レベル3のメモリを指定する |
TA_NORESIDENT | 非常駐メモリを指定する |
TA_RNGn では、メモリのアクセスを制限する保護レベルを指定する。割り当てられたメモリは、指定された保護レベルと同じかより高い保護レベルで実行しているタスク等からのみアクセス可能である。
TA_NORESIDENT が指定された場合、割り当てられたメモリは非常駐メモリとなる。MMUのないシステムでは、非常駐メモリの属性を指定した場合でも、実際には常駐メモリと同様の動作をすることになるが、エラーとはしない。
nblk
に負の値が指定された場合や、attr
に指定できない属性が指定された場合には、E_PAR のエラーを返す。また、addr
の指すメモリ(割り当てたメモリの先頭アドレスを返す領域)への書込みアクセスが禁止されている場合には、E_MACV のエラーを返す。
nblk
で指定したブロック数分の連続したメモリ領域の割当てができない場合、E_NOMEM のエラーを返す。この場合、addr
の指すメモリには NULL が返される。
MMUを使用しないシステムでは、実装上、メモリの保護レベルに違反したアクセスがあった場合にも、アクセス権違反の例外を検出することができず、正常なメモリアクセスができてしまう。しかし、プログラムの移植性や拡張性を考慮し、割り当てるメモリに対しては、アクセスするタスク等の保護レベルからアクセス可能な適切な保護レベルを指定することが推奨される。
addr
で指定したメモリを解放する。addr
は、tk_get_smb() で得たアドレスでなければならない。
addr
に指定されたアドレスが不正であることが検出された場合は、E_PAR のエラーが返る。具体的には、addr
がT-Kernelが管理しているメモリの範囲外を指している場合や、既に tk_rel_smb() で解放したメモリを再度解放しようとした場合に、E_PAR エラーが返る。ただし、実装上の制約により、addr
が不正であってもエラーの検出ができない場合があり、その場合の動作は保証されない。そのため、addr
の正当性は呼出側で保証しなければならない。
pk_rsmb
の内容
システムメモリに関する情報を取得する。
仮想記憶を行っているシステムでは、非常駐のメモリを割り当てることにより、物理的なメモリよりも大きなサイズのメモリを使うことができる。このため、全ブロック数や残りブロック数が一意に決定できないことがある。そのような場合の total
, free
の内容は実装依存とするが、free
÷total
が残りメモリ容量の割合の参考値となるような値とすることが望ましい。
tk_get_smb() によるシステムメモリの割当てはブロック単位であるため、より細分化して効率的にメモリを使用するために、メモリ割当てライブラリを使用する。
メモリ割当てライブラリの内部では、tk_get_smb() によって確保されたシステムメモリを管理しており、その中からアプリケーションの要求したサイズのメモリを割り当てる。メモリ割当てライブラリが管理するメモリに、アプリケーションが要求するサイズの空きメモリが無い場合には、再度 tk_get_smb() を呼び出して追加のシステムメモリを割り当てる。
一方、アプリケーションからメモリが返却された際に、そのメモリが含まれるメモリブロックのすべてが未割当てとなった場合には、tk_rel_smb() によってそのメモリブロックを解放する。ただし、メモリブロックの確保や解放の厳密なタイミングなどは実装依存である。
メモリ割当てライブラリは、C言語標準ライブラリの malloc
/calloc
/realloc
/free
と同等の機能が提供される。対象とするメモリが非常駐メモリの場合は V~ のAPI名、常駐メモリの場合は K~ のAPI名である。
これらのメモリは、すべて TSVCLimit
で指定された保護レベルのメモリとして割り当てられる。
なし
size
で指定したバイト数の非常駐メモリを割り当て、その先頭アドレスを addr
に返す。
指定したサイズのメモリの割当てができなかった場合や、size
に0が指定された場合は、addr
に NULL が返る。
Vmalloc を含むメモリ割当てライブラリのAPIは、タスク独立部およびディスパッチ禁止中、割込み禁止中に呼び出すことはできない。呼び出した場合の動作は、システムダウンの可能性も含めて不定であり、呼出時の状態を保証するのは、呼出側の責任である。
size
には任意の値を指定できるが、管理領域の確保や、割り当てるメモリアドレスのアラインメントの調整といった理由により、内部的には、size
で指定したバイト数よりも大きなメモリが割り当てられる場合がある。たとえば、割当て可能なメモリサイズの最低が16バイトで、アラインメントが8バイト単位という実装の場合には、size
に16バイト未満の値を指定した場合でも、内部的には16バイトのメモリが割り当てられる。また、size
に20バイトの値を指定した場合でも、内部的には24バイトのメモリが割り当てられる。
したがって、メモリ割当てライブラリ全体で使用するシステムメモリのサイズと、メモリ割当てライブラリの各APIで割り当てられたメモリのサイズの合計を比較すると、前者の方が大きな値をとる場合がある。
なし
size
で指定したバイト数のメモリブロックを、nmemb
で指定された個数だけ連続して割り当て、0クリアしてから、その先頭アドレスを addr
に返す。メモリ割当ての動作は、size
と nmemb
を乗じたバイト数のメモリブロック1個を割り当てるのと同じである。割り当てられるメモリは、非常駐メモリである。
指定した個数のメモリブロックの割当てができなかった場合や、nmemb
または size
に0が指定された場合は、addr
に NULL が返る。
Vcalloc を含むメモリ割当てライブラリのAPIは、タスク独立部およびディスパッチ禁止中、割込み禁止中に呼び出すことはできない。呼び出した場合の動作は、システムダウンの可能性も含めて不定であり、呼出時の状態を保証するのは、呼出側の責任である。
なし
ptr
で指定した割当て済の非常駐メモリのサイズを、size
で指定されたサイズに変更する。その際にメモリの再割当てを行い、再割当て後のメモリの先頭アドレスを addr
に返す。
サイズ変更をともなうメモリの再割当てにより、一般にはメモリの先頭アドレスが移動し、addr
は ptr
と異なった値になる。ただし、その場合でも、再割当ての対象となったメモリの内容は保存される。このため、Vrealloc の処理の中でメモリ内容のコピーを行う。また、再割当てにより不要になったメモリは解放される。
ptr
には、Vmalloc、Vcalloc、Vrealloc で割り当てられたメモリの先頭アドレスを指定する必要がある。ptr
の正当性は呼出側で保証しなければならない。
ptr
に NULL を指定した場合は、新しいメモリの割当てのみを行う。この場合の動作は Vmalloc() と同一である。
指定したサイズのメモリの再割当てができなかった場合や、size
に0が指定された場合は、addr
に NULL が返る。このとき、ptr
に NULL 以外が指定されていれば、ptr
のメモリの解放だけを行う。この場合の動作は Vfree() と同一である。
Vrealloc を含むメモリ割当てライブラリのAPIは、タスク独立部およびディスパッチ禁止中、割込み禁止中に呼び出すことはできない。呼び出した場合の動作は、システムダウンの可能性も含めて不定であり、呼出時の状態を保証するのは、呼出側の責任である。
なし
なし
size
で指定したバイト数のメモリブロックを、nmemb
で指定された個数だけ連続して割り当て、0クリアしてから、その先頭アドレスを addr
に返す。メモリ割当ての動作は、size
と nmemb
を乗じたバイト数のメモリブロック1個を割り当てるのと同じである。割り当てられるメモリは、常駐メモリである。
指定した個数のメモリブロックの割当てができなかった場合や、nmemb
または size
に0が指定された場合は、addr
に NULL が返る。
Kcalloc を含むメモリ割当てライブラリのAPIは、タスク独立部およびディスパッチ禁止中、割込み禁止中に呼び出すことはできない。呼び出した場合の動作は、システムダウンの可能性も含めて不定であり、呼出時の状態を保証するのは、呼出側の責任である。
なし
ptr
で指定した割当て済の常駐メモリのサイズを、size
で指定されたサイズに変更する。その際にメモリの再割当てを行い、再割当て後のメモリの先頭アドレスを addr
に返す。
サイズ変更をともなうメモリの再割当てにより、一般にはメモリの先頭アドレスが移動し、addr
は ptr
と異なった値になる。ただし、その場合でも、再割当ての対象となったメモリの内容は保存される。このため、Krealloc の処理の中でメモリ内容のコピーを行う。また、再割当てにより不要になったメモリは解放される。
ptr
には、Kmalloc、Kcalloc、Krealloc で割り当てられたメモリの先頭アドレスを指定する必要がある。ptr
の正当性は呼出側で保証しなければならない。
ptr
に NULL を指定した場合は、新しいメモリの割当てのみを行う。この場合の動作は Kmalloc() と同一である。
指定したサイズのメモリの再割当てができなかった場合や、size
に0が指定された場合は、addr
に NULL が返る。このとき、ptr
に NULL 以外が指定されていれば、ptr
のメモリの解放だけを行う。この場合の動作は Kfree() と同一である。
Krealloc を含むメモリ割当てライブラリのAPIは、タスク独立部およびディスパッチ禁止中、割込み禁止中に呼び出すことはできない。呼び出した場合の動作は、システムダウンの可能性も含めて不定であり、呼出時の状態を保証するのは、呼出側の責任である。