プロセス・スレッドモデルの違い — INtime オブジェクト指向カーネル vs RTX64 RTSSプロセス【移行ガイド】

コーディング

INtime でプロセスやスレッドを書いてきたエンジニアが RTX64 に移行すると、最初に戸惑うのがプロセス・スレッドの「作り方」の違いです。INtime はオブジェクト指向カーネルとして GDT スロットと RTHANDLE でリソースを統一管理しますが、RTX64(RTSS)は Windows のプロセスモデルを継承した独自サブシステムです。概念と API の対応を理解することが移行の第一歩となります。

INtime のプロセスモデル — オブジェクト指向カーネルとプロセスツリー

INtime カーネルはすべてのリソースを「カーネルオブジェクト」として統一管理します。プロセス、スレッド、セマフォ、リージョン、メールボックス — あらゆるものが RTHANDLE で識別されるカーネルオブジェクトです。

プロセスは ツリー構造(プロセスツリー)を形成します。システム起動時に Root Process が生成され、すべてのアプリケーションプロセスはその子孫として存在します。各プロセスはリソース(メモリプール)を親プロセスから取得します。

Root Process(カーネル起動時に生成)
├─ System Process A(カーネルシステムプロセス)
├─ System Process B
└─ Your Application Process(CreateRtProcess で起動)
    ├─ Thread 1(メインスレッド)
    └─ Thread 2(ユーザー作成スレッド)

GDT スロット — INtime のリソース管理の核心

INtime がオブジェクト指向と呼ばれる理由のひとつが、GDT(Global Descriptor Table)によるリソース管理です。プロセッサの GDT は、メモリセグメントの記述子を管理するテーブルです。INtime はこの GDT のスロットを利用して、すべてのカーネルオブジェクトを管理しています。

重要な制限事項として、システム全体で高レベルオブジェクトは約 7,600 個までという上限があります(GDT の 8,192 スロットのうち、OS 自体が使用するスロットを除いた数)。この上限を超えると E_SLOT (0x000C) エラーが返されます。

// INtime: CreateRtThread の戻り値チェック
RTHANDLE hThread = CreateRtThread(
    NULL_RTHANDLE,   // 親プロセス(NULL = 呼び出し側プロセス)
    0,               // スタックサイズ(0 = デフォルト)
    100,             // 優先度(0が最高、254が最低)
    myThreadFunc,    // スレッド関数
    NULL             // 引数
);

if (hThread == NULL_RTHANDLE)
{
    DWORD err = GetLastRtError();
    if (err == E_SLOT)
    {
        // GDT スロットが満杯 — オブジェクト数が上限に達している
        printf("ERROR E_SLOT: GDT slots full. Too many RT objects.
");
    }
}

GDT スロット制限は INtime 独自の制約です。RTX64 に移行すると、この制限はなくなります(Windows カーネルのリソース制限が適用されます)。

INtime のメモリプール — 事前割り当て型メモリ管理

INtime の各プロセスは メモリプール(Memory Pool)と呼ばれる独自のメモリ空間を持ちます。プロセス内のすべてのスレッドはこのプールを共有しますが、異なるプロセス間ではメモリプールを共有できません。

メモリプールのサイズはリンカーの /HEAP パラメータまたは RT Application Loader のオプションで指定します。INtime はメモリを事前確保するため、リアルタイム動作中に動的なメモリ割り当てが発生しません。

// INtime: プロセスのメモリプール情報を取得
POOLINFO poolInfo;
DWORD ret = GetRtProcessPoolInfo(NULL_RTHANDLE, &poolInfo);
// poolInfo.dwUsed  : 使用中バイト数
// poolInfo.dwTotal : プール総サイズ

RTX64(RTSS)のプロセスモデル — Windows HAL 拡張

RTX64 は Windows の HAL(Hardware Abstraction Layer)を拡張する形で動作します。RTSS は Windows とは独立したサブシステムとして存在しますが、プロセスモデルは Windows の考え方を継承しています。

RTSSプロセスは フラット構造で、INtime のようなツリー階層はありません。プロセスの実行ファイルには .rtss という拡張子が付きます。

Windows OS
├─ Windowsプロセス A(.exe)
├─ Windowsプロセス B(.exe)
└─ RTSS サブシステム(Windows とは独立して動作)
    ├─ RTSSプロセス 1(.rtss)— リアルタイム制御アプリ
    └─ RTSSプロセス 2(.rtss)— モーション制御アプリ(WMX3等)

別の RTSSプロセスを起動するには、Windows 側のアプリから RtCreateProcess() を呼び出します(RTSS プロセス内から直接別の RTSS プロセスを作成することはできません)。

// RTX64: Windows アプリから RTSS プロセスを起動する
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi = {};

BOOL ok = RtCreateProcess(
    L"C:\RtApps\motion.rtss",  // 絶対パス必須(相対パス不可)
    nullptr,                      // コマンドライン引数
    nullptr, nullptr,             // セキュリティ属性
    FALSE,                        // ハンドル継承なし
    0,                            // 作成フラグ
    nullptr,                      // 環境変数
    L"C:\RtApps",               // 検索ディレクトリ(省略可)
    &si, &pi
);

if (!ok)
{
    DWORD err = GetLastError();
    // エラー処理
}
// pi.hProcess, pi.hThread が作成された
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

RTDLL — RTX64 の動的ライブラリ(INtime の共有ライブラリに相当)

INtime では共有ライブラリ(RTA 形式)を使いますが、RTX64 では RTDLL(Real-Time Dynamic Link Library)という独自の DLL を使用します。拡張子は .rtdll です。

項目INtime(共有ライブラリ)RTX64(RTDLL)
ファイル形式.rta(RTアプリ/ライブラリ).rtdll
ロード方式ノードローカル管理暗黙的ロード(リンク) / 明示的ロード(LoadLibrary)
プロセス間共有ノード単位で共有可能共有不可(各プロセスが独自イメージを持つ)
初期化関数独自初期化DllMain(DLL_PROCESS_ATTACH/DETACH)
スレッド通知-DLL_THREAD_ATTACH/DETACH は非サポート
Windows DLL との互換なしWindows アプリからは通常の .dll を使用

RTDLL の重要な制限として、プロセス間では共有されない点に注意が必要です。2 つの RTSS プロセスが同じ RTDLL ファイルをロードした場合、それぞれが独自のメモリイメージを持ちます。したがって、RTDLL 内のグローバル変数はロードしたプロセスにプライベートです。

スレッドの比較 — 優先度・アフィニティの違い

スレッドの作成方法と優先度体系が INtime と RTX64 では大きく異なります。

項目INtimeRTX64(RTSS)
スレッド作成 APICreateRtThread()CreateThread()(Windows と同じ)
スレッドハンドル型RTHANDLEHANDLE(Windows 互換)
優先度範囲0〜254(0 が最高)0〜127(0 が最高)
プロセス優先度クラスあり(プロセスの最大優先度制限)なし(スレッド優先度のみで制御)
アフィニティノード内のコアに割り当て可能Static モデル(動的移動なし、Ideal Processor 保証)
優先度設定 APISetRtThreadPriority()RtSetThreadPriority()
// INtime: スレッド作成と優先度設定
RTHANDLE hThread = CreateRtThread(
    NULL_RTHANDLE,   // 親プロセス
    0,               // スタックサイズ(0=デフォルト)
    50,              // 優先度(0〜254、INtime では数値が小さい = 高優先度)
    myRtThreadFunc,
    NULL
);

// RTX64(RTSS): Windows CreateThread に近い形
HANDLE hThread = CreateThread(
    nullptr,         // セキュリティ属性
    0,               // スタックサイズ(0=デフォルト)
    myRtssThreadFunc,
    nullptr,
    0,
    nullptr
);
// 優先度は別途設定
RtSetThreadPriority(hThread, 50);  // 0〜127(0が最高)

ハンドル型の対応 — RTHANDLE vs HANDLE

INtime では RTHANDLE がすべてのカーネルオブジェクトを統一的に表しますが、RTX64 では Windows の HANDLE 型がその役割を担います。

// INtime の主要な RTHANDLE 利用例
RTHANDLE hProcess;   // プロセスハンドル
RTHANDLE hThread;    // スレッドハンドル
RTHANDLE hSem;       // セマフォハンドル
RTHANDLE hRegion;    // リージョン(ミューテックス相当)ハンドル
RTHANDLE hMailbox;   // メールボックスハンドル

// RTX64(RTSS)の HANDLE 利用例(Windows 互換型)
HANDLE hThread;      // スレッドハンドル
HANDLE hEvent;       // イベントハンドル(RtCreateEvent)
HANDLE hMutex;       // ミューテックスハンドル(RtCreateMutex)
HANDLE hSem;         // セマフォハンドル(RtCreateSemaphore)

全体比較まとめ

比較項目INtimeRTX64(RTSS)
カーネルの思想オブジェクト指向 RTOS(独自カーネル)Windows HAL 拡張(RTSS サブシステム)
プロセス構造ツリー(Root → 親 → 子)フラット(Windows と並列)
リソース管理基盤GDT スロット(約 7,600 個上限)Windows カーネルリソース
ハンドル型RTHANDLEHANDLE(Windows 互換)
動的ライブラリ.rta(共有ライブラリ).rtdll(プロセス非共有)
スレッド優先度0〜254(0 が最高)0〜127(0 が最高、クラスなし)
メモリ管理メモリプール(事前割り当て、/HEAP 指定)ロック済み仮想メモリ(malloc 可)
プロセス起動 APICreateRtProcess() / ntxCreateRtProcess()RtCreateProcess()(Windows 側から)

移行時の注意点

  • GDT スロット制限はなくなる:INtime では最大 7,600 オブジェクトという制限がありましたが、RTX64 ではこの制限がなくなります。ただし Windows カーネルのリソース制限(HANDLE数など)は別途あります。
  • RTHANDLE → HANDLE への読み替え:ハンドル型が変わるため、既存コードの型宣言をすべて見直す必要があります。
  • スレッド優先度の範囲縮小:INtime の 0〜254 から RTX64 の 0〜127 に半減します。優先度設計を見直してください。
  • RTDLL はプロセス間共有不可:グローバル変数を複数プロセスで共有していた場合は、共有メモリ(RtCreateSharedMemory)への移行が必要です。
  • DLL_THREAD_ATTACH/DETACH が来ない:RTDLL の DllMain ではスレッドの通知を受け取れません。スレッドローカルな初期化は別の方法で行ってください。
  • プロセス起動は Windows 側から:RTX64 では RTSS プロセス内から直接別の RTSS プロセスを起動する仕組みがありません。起動制御は Windows アプリが担います。

終わりに

日本では、INtimeユーザが多いとよく聞きます。けど、WMXを使うにはRTXを使う必要があります。開発環境が2つになってしまった方へ少しでも戸惑いが減りますように。 良きWMXライフを!

コメント

タイトルとURLをコピーしました