Linux on ITRON Linux on ITRON Linux on ITRON Linux on ITRON
―ハイブリッド構造の実装
―ハイブリッド構造の実装
―ハイブリッド構造の実装
―ハイブリッド構造の実装
株式会社エルミックシステム 金田一 勉
『 Interface』2002 年 7 月号別冊付録掲載
目次 目次 目次 目次
目次... 2
1.Linuxにおけるリアルタイム処理... 3
2.ハイブリッド構造... 4
3.ハイブリッド技術への期待... 5
4.Linuxを組込みシステムへ活用する試み ―― Emblix... 6
4.1 ハイブリッド構造への仕様... 6
4.2 仕様の概要... 7
5.OS間インタフェース... 8
5.1 FIFO方式... 8
5.2 共有メモリブロック方式...11
6.ハイブリッド構造の構築...14
6.1 二つのOSのスケジューラ...14
6.2 Linuxの動作環境...17
6.3 割込み制御...18
7.リアルタイムOSとハイブリッド構造...20
8.ハイブリッド構造の実装時の注意...21
9.実装例...22
9.1 初期化...22
9.2 割込み処理/割込み制御...25
9.3 OS間インタフェース...28
9.4 ITRON仕様準拠カーネルについて...29
10.その他の実装例...30
10.1 割込み処理/割込み制御...30
10.2 ITRONシステムの開発環境...30
10.3 ITRONシステム...31
11.ハイブリッド構造のシステム構築...32
おわりに...33
1. 1. 1.
1.Linux Linux Linux Linux におけるリアルタイム処理 におけるリアルタイム処理 におけるリアルタイム処理 におけるリアルタイム処理
Linuxを利用したシステムでリアルタイム処理を行わせる方法としては、おもに3つある。
① スケジューラをリアルタイムスケジューラに置き換える
② カーネルモードで動作するタスクを管理できるようにする
③ RTOSとのハイブリッド構造を構築する
①は、Linuxのスケジューラをプリエンプティブなスケジューラに置き換える方法である。
②は、プロセスはユーザモードで動作するため、いろいろな制約を受ける。カーネルモードでタスクを動作させ ることで、そのような制約を受けずに処理を高速化することができる。
③は、リアルタイム処理はRTOSシステムで行い、LinuxとRTOSとの融合を行う方法である。本章では、③
のLinuxとRTOSとのハイブリッド構造の構築について説明する。
2.ハイブリッド構造 2.ハイブリッド構造 2.ハイブリッド構造 2.ハイブリッド構造
本章におけるハイブリッド構造とは、LinuxとRTOSとの二つのOSが一つのCPU上で動作し、Linuxおよび RTOSのシステムは、それぞれのカーネルが制御を行う構造のものをいう。
ハイブリッド構造をとることにより、LinuxおよびRTOSそれぞれがもつ利点を活かすことができる。Linuxが もつネットワーク機能やGNUツール、ファイルシステムなどの機能が利用でき、RTOSではリアルタイム処理が 可能となる(図1)。
〔図〔図
〔図〔図 1111〕〕〕〕ハイブリッド構造をもつシステムの利点ハイブリッド構造をもつシステムの利点ハイブリッド構造をもつシステムの利点ハイブリッド構造をもつシステムの利点
人間やコンピュータとの コミュニケーション
機械制御 RTOS
Linux
3.ハイブリッド技術への期待 3.ハイブリッド技術への期待 3.ハイブリッド技術への期待 3.ハイブリッド技術への期待
日本の組込みシステムの多くがITRON仕様に準拠したOSを使用している。ITRONではソフトウェア部品が 少ないことから、Linuxがもつ各種機能やソフトウェア部品の利用への期待が高まっている。組込みシステムには リアルタイム処理が必要になる場合が多いが、Linuxは決してリアルタイム性があるとはいえない。
Linuxに対し、リアルタイム処理ができるようなしくみをもった製品も出荷されている。RT LinuxやTimeSys
Linuxがそれである。これらは、カーネルモードでプログラムを動作させるしくみをもち、カーネルモードで動作
するプログラムを優先的に動作させている。また、カーネルモードで動作するため、仮想化処理が間になく、直接 ハードウェア制御を行うことができる。
カーネルモードで動作するプログラムと、通常のLinuxのプロセスとは、特殊なインタフェースAPIを使って 情報通知を行うしくみをもっている。カーネルモードで動作するプログラムは、Linux上のプロセスの開発方法と 異なるため、機能やAPIを学習する必要がある。前述したように日本の組込みシステムの多くがITRON仕様に準 拠したOSを使用しているので、各企業にはITRONのプログラム資産が数多く存在する。
ここでいう「プログラム資産」とは、組込みシステムを構成するプログラム自体だけでなく、システムの動作を 検証するプログラムや、そのシステムのために開発したソフトウェア部品やライブラリなども含んでいる。
これらのソフトウェア資産は、ITRON上で動作することを前提に作成しているところもあるので、OSが変更に なった場合、それらのソフトウェア部品の改造および検証を再び行う必要がある。
OSを変更し、そのOSがもつ機能を利用したシステムを開発することで開発工数の短縮を図っても、従来から もっているソフトウェア資産への改造および検証で開発工数がかかってしまうことが考えられる。
LinuxとITRONとのハイブリッド構造をもつことで、Linuxがもつ機能を利用しながら、ITRON用のソフト
ウェア資産を使用できる。ITRON 上で動作するシステムは、カーネルモードでの動作になるので、リアルタイム 処理を行うことができる。また、Linuxの動作よりITRONシステムの動作を優先するしくみになっているので、
ITRONシステムだけで動作していた環境とそれほど変わらない。
このように、ハイブリッド技術を使うことで、ユーザはLinuxがもつ機能を利用することができ、さらに従来の ソフトウェア資産の有効活用も可能になる。ユーザは、ハイブリッド技術の実現により、組込みシステムの開発工 数の大幅な短縮を期待している。
また、マンマシン・インタフェースなどを行うためのシステムとリアルタイム処理を行うためのシステムが2台 のハードウェア上に別々にあり、そのハードウェア間でデータ通信を行うことで、全体のシステムを構成している ものもある。
このようなシステムに対して、ハイブリッド構造を使ってシステムが構築できるようになると、ハードウェアが 1台になり、かつシステム間のデータ通信を外部機器なしに行うことができる。
ソフトウェアで使用するハードウェアが1台になると、システム全体のハードウェア原価が低くなり、できあが る製品の単価を安くできる。また、製品も小さくすることが可能になる。ユーザは、ハイブリッド技術の実現によ り、製品の生産原価の低減も期待できる。
4. 4. 4.
4.Linux Linux Linux Linux を組込みシステムへ活用する試み を組込みシステムへ活用する試み を組込みシステムへ活用する試み を組込みシステムへ活用する試み ―― ―― ―― ―― Emblix Emblix Emblix Emblix
昨今、Linuxは、組込みシステムへの採用が期待されている。産学協同の団体であるEmblix(日本エンベデッ
ド リナックス コンソーシアム)では、Linuxを組込み業界に普及、浸透させることと、周辺技術の標準化と情報 交換を目的として活動している。Emblix には、現在三つのワーキンググループがあり、その一つである「ハイブ リッドアーキテクチャWG」では、LinuxとRTOSとのハイブリッド構造についての仕様の策定を行っている。
4.1 ハイブリッド構造への仕様
この仕様の目的は、LinuxとRTOSとのハイブリッド構造をもつ製品に対して基準を設けることで、ハイブリッ ド構造をもつ製品間の互換性をもたせようというものである。そのために、ハイブリッド構造をもつシステムの動 作とOS間インタフェースについて規定している。
仕様を策定する際に、その前提や方針を決めている。
① Linux本体への改変はせず、アーキテクチャ依存部分への改変にとどめる
② RTOSのリアルタイム性を損なわないようにする
③ LinuxとRTOS間とで情報の交換の手段を規定する
④ RTOSのシステムは、CPUのスーパバイザモードで動作する
⑤ LinuxはRTOSのタスクとして動作させる
⑥ ハードウェアの共有は行わない
⑦ 割込みの共有は行わない
①については、LinuxのバージョンやベンダごとのLinuxに依存しないようにすることで、各種のLinuxでの ハイブリッド構造の構築を可能とする。
②については、RTOSを利用する理由がリアルタイム処理を行うことでもあるので、リアルタイム性が損なわれ ないような仕様とする。
③については、LinuxとRTOSとが個別に動作するだけでなく、OS間で情報交換を行うことで、お互いの機能 を有効に活用することができる。そのための情報交換の手段を規定することで、ハイブリッド構造をもつ製品の互 換性ができる。
④については、RTOSのシステムはリアルタイム性を保つためにCPUのスーパバイザモードでの動作とした。
⑤については、ハイブリッド構造を構築するにあたり、スケジューリングはRTOSが行うこととした。Linuxは RTOSのタスクとして制御される。
⑥については、ハードウェアをLinuxとRTOSとで共有する場合、ハードウェアの制御を行うのが困難になる。
そのため、二つのOSで同じハードウェアの制御は行わず、どちらかがその制御を行い、他のOSがそのハードウ ェアを利用したい場合は、OS間インタフェースを利用して要求する。
4.2 仕様の概要
1 11
1)優先順位)優先順位)優先順位)優先順位
RTOSのリアルタイム性を損なわないようにするために、仕様で決めた基本的な動作優先順位を示す。
RTOS側割込み処理 高い
RTOS側カーネル,スケジューラ RTOS側タスク
Linux側割込み処理
Linux側カーネル,ボトムハーフ,スケジューラ
Linux側プロセス 低い
ただし、実装により一部優先順位の変更はかまわない。たとえば、RTOS側タスクとLinux側割込み処理の優先 順位を実装で逆に定義してもよい。この場合、RTOS側タスク動作中でもLinux側の割込みを受け付けることがで きるようになる。
2222)))Linux)LinuxLinuxLinuxタスクタスクタスク タスク
Linuxの動作環境をRTOS上のタスクとして動作させる。このタスクを「Linuxタスク」と呼んでいる。この
Linuxタスクは基本的に、RTOSシステムの中でいちばん優先度が低いタスクとしている。
3333)))OS)OSOSOS間インタフェース間インタフェース間インタフェース間インタフェース
LinuxとRTOSとの情報交換を行うためのインタフェースの方式を決めた。
FIFO方式
共有メモリブロック方式
FIFO 方式は、バイト単位でデータの送受信を行う方法である。共有メモリブロック方式は、OS 間で共有する メモリ領域を定義し、その領域を排他制御することで情報の交換を行う方法である。
4444)ハイブリッド構造の概要)ハイブリッド構造の概要)ハイブリッド構造の概要 )ハイブリッド構造の概要
Emblix における仕様の策定時にモデ
ルとした構造の概要を図2に示す。
図2において、Linux環境はRTOSカ ーネルのタスクとして動作する。割込み 調停機能とは、割込み発生時にその割込 み要因によりRTOSもしくはLinuxの 割込みハンドラに制御を渡すものである。
Linux環境にあるRTOS ドライバと
は、OS間インタフェースのためにLinux
側に組込むデバイスドライバを示す。
〔図
〔図
〔図〔図 2222〕〕〕〕ハイブリッド構造のモデルハイブリッド構造のモデルハイブリッド構造のモデルハイブリッド構造のモデル
Linux 環境 RTOS環境
RTOS タスク Linux
プロセス
割込み調停機能 Linux デバイス
ドライバ
RTOS ドライバ
OS間 インタフェース
機能 OS間
インタフェース Linux カーネル
RTOSカーネル
5. 5. 5.
5.OS OS OS OS 間インタフェース 間インタフェース 間インタフェース 間インタフェース
LinuxとRTOS間との情報交換のための手段としてOS間インタフェースを設ける。OS間インタフェースは、
Emblixの仕様により、FIFO方式と共有メモリブロック方式とする。Emblixの仕様では、Linux側のデバイスド
ライバの処理動作と、RTOS側のAPIおよび処理動作を定義している。
5.1 FIFO 方式
FIFO方式は、LinuxからRTOSへもしくはRTOSからLinuxへのバイト単位での情報通知の手段である。OS
間インタフェースで使用するFIFO方式に必要な管理ブロックやメモリ領域などはRTOS(μITRON仕様準拠OS)
側で用意するものとしている。
FIFO方式を実装する場合、一つのFIFOに対し、内部的にLinuxからRTOSへのデータ通信用、RTOSから
Linuxへのデータ通信用の二つのFIFOバッファをもつ。FIFO方式をサポートするデバイスドライバのノードと
RTOSのFIFOカーネルオブジェクトとが対応する(図3)。
〔図〔図
〔図〔図 3333〕〕〕〕FIFOFIFOFIFOFIFO方式方式方式方式
Linux環境環境環境 環境 RTOS環境環境環境環境
プロセスプロセス プロセスプロセス
バッファ バッファ バッファ バッファ
デバイスドライバ デバイスドライバ デバイスドライバ デバイスドライバ
write read
データ コピー
データ コピー
OS間間間間 インタフェース機能 インタフェース機能 インタフェース機能 インタフェース機能
タスクタスクタスク タスク
バッファ バッファバッファ バッファ
read 要求 write
要求 FIFO
FIFO FIFO FIFOバッファバッファバッファ バッファ
1)1)1)
1)LinuxLinuxLinuxLinux側側側API側APIAPIAPI
Linuxプロセスは、FIFO方式をサポートするデバイスドライバをopenし、取得できるファイルディスクリプタ
を用いwrite(書き込み)/read(読み出し)の要求を行う。write要求は、LinuxプロセスからRTOSタスク への情報送信になる。read要求は、RTOSタスクからLinuxプロセスへの情報受信になる。
open要求
【API】
int open(char *pathname, int flags);
char *pathname :FIFO方式をサポートするデバイスドライバのパス名 int flags :フラグ
【説明】
FIFO方式をサポートするデバイスドライバをopenする。
flagsには、 O_RDONLY(読み出し専用), O_WRONLY(書き込み専用), O_RDWR(読み書き用) のどれか 一つを要求する。flagsはさらに以下の定数とのビットORを指定することができる。
O_NONBLOCK または O_NDELAY
デバイスドライバを非閉塞(non-blocking)モードでopenする。
read要求
【API】
ssize_t read(int fd, void *buf, size_t count);
int fd : FIFO方式をサポートしたデバイスドライバのファイルディスクリプタ void *buf : 読み出すバッファのアドレス
size_t count : 読み出しサイズ
【説明】
RTOS側からのデータを受信する。受信したサイズを返却値として返却する。
閉塞モードでopenしている場合は、読み出しサイズ分のデータが読み出せるまで待ち状態になるが、要求サイ ズ以下で返却される場合もある。
非閉塞モードでopenしている場合は、要求時にFIFOバッファにあるデータを読み出し、そのサイズを返却値 として返却する。
write要求
【API】
ssize_t write(int fd, const void *buf, size_t count);
int fd : FIFO方式をサポートしたデバイスドライバのファイルディスクリプタ void *buf : 書き込むデータバッファのアドレス
size_t count : 書き込みサイズ
【説明】
RTOSに対しデータを送信する。送信したサイズを返却値して返却する。
閉塞モードでopenしている場合は、書き込みサイズ分のデータが書き込めるまで待ち状態になるが、要求サイ ズ以下で返却される場合もある。
非閉塞モードでopenしている場合は、要求時にFIFOバッファに書き込めるデータを書き込み、そのサイズを 返却値として返却する。
2)2)2)
2)RTOSRTOSRTOSRTOS側側側側APIAPIAPIAPI
OS間インタフェースとしてのFIFO方式のオブジェクトは、新規のカーネルオブジェクトとして定義する。RTOS のタスクがFIFO方式のオブジェクトを指定してLinux側との情報交換を行う。Emblixの仕様で定義したAPIを 説明する。
読み出し要求
【API】
ER_INT lii_rea_fif(ID fifid, VP buf, INT len, TMO tmout);
ID fifid : 読み出し対象の FIFO の ID 番号 VP buf : 読み出しデータを入れる領域の先頭番地 INT len : 読み出すデータの長さ(バイト単位)
TMO tmout : タイムアウト指定
【説明】
指定するFIFO方式のオブジェクトからデータを受信する。受信したサイズを返却値として返却する。
本要求により読み出すことができたサイズを返却値として返却する。
タイムアウトは、ms単位の時間を指定できるが、TMO_POL(ポーリング)、TMO_FEVR(永久待ち)の指定もで きる。
書き込み要求
【API】
ER_INT lii_wri_fif(ID fifid, VP buf, INT len, TMO tmout);
ID fifid : 書き込み対象の FIFO の ID 番号 VP buf : 書き込むデータが入った領域の先頭番地 INT len : 書き込むデータの長さ(バイト単位)
TMO tmout : タイムアウト指定
【説明】
指定するFIFO方式のオブジェクトにデータを送信する。送信できたサイズを返却値として返却する。
本要求により書き込むことができたサイズを返却値として返却する。
タイムアウトは、ms単位の時間を指定できるが、TMO_POL(ポーリング)、TMO_FEVR(永久待ち)の指定もで きる。
リセット要求
【API】
ER lii_rst_fif(ID fifid, ATR fifatr);
ID fifid : リセット対象の FIFO の ID 番号 ATR fifatr : FIFO 属性
【説明】
FIFOバッファをリセット(データを破棄)する。
FIFO 属性には TA_READ(受信 FIFO バッファの指定)、TA_WRITE(送信 FIFO バッファの指定)、
TA_READ|TA_WRITE(受信,送信FIFOバッファ両方の指定)のいずれかを指定する。
5.2 共有メモリブロック方式
共有メモリブロック方式は、LinuxとRTOSとで共有するメモリ領域をもち、その領域を排他的に使用しながら 情報通知する手段である。OS 間インタフェースで使用する共有メモリブロック方式に必要な管理ブロックやメモ リ領域などはRTOS側で用意するものとしている。共有メモリブロック方式をサポートするデバイスドライバのノ ードとRTOSの共有メモリブロックのカーネルオブジェクトとが対応する(図4)。
〔図
〔図〔図
〔図4444〕〕〕〕共有メモリブロック方式共有メモリブロック方式共有メモリブロック方式共有メモリブロック方式
共有メモリ領域 共有メモリ領域 共有メモリ領域 共有メモリ領域 アクセス アクセス プロセス
プロセスプロセス プロセス
デバイスドライバ デバイスドライバ デバイスドライバ デバイスドライバ アン ロック
ロック
OS間間間 間 インタフェース機能 インタフェース機能インタフェース機能 インタフェース機能
タスクタスク タスクタスク
アン ロック ロック
1)
1)1)
1)LinuxLinuxLinuxLinux側側側API側APIAPIAPI
Linuxプロセスは、共有メモリブロック方式をサポートするデバイスドライバをopenし、取得できるファイル
ディスクリプタを用いて共有メモリブロックのアドレスを取得し、共有メモリ領域にアクセスを行う。共有メモリ ブロックを排他制御するために、ioctlにてデバイスドライバにlock/unlockを要求する。
open要求
【API】
int open(char *pathname, int flags);
char *pathname : 共有メモリブロック方式をサポートするデバイスドライバのパス名 int flags : フラグ
【説明】
共有メモリブロック方式をサポートするデバイスドライバをopenする。
mmap要求
【API】
void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
void *addr : 希望アドレス size_t len : 領域サイズ
int prot : 保護方式PROT_READ、PROT_WRITEのいずれかもしくは両方を指定
int flags : フラグMAP_SHAREDもしくはMAP_PRIVATEのいずれかを指定
int fd : 共有メモリブロック方式をサポートするデバイスドライバのファイルディスクリプタ
off_t offset : オフセット
【説明】
mmapサービスコールで、共有メモリ領域の仮想アドレスを取得する。
プロセスは、取得した共有メモリ領域の仮想アドレスを使用して、共有メモリ領域にアクセスを行う。
共有メモリ領域を排他的に使用する場合は、ioctlを要求する。
ioctl要求
【API】
int ioctl(int fd, int request, int *argp);
int fd : 共有メモリブロック方式をサポートするデバイスドライバのファイルディスクリプタ int request : コマンド コマンドにはSMBLOCK、SMBUNLOCKがある
int *argp : 引数
【説明】
コマンドにSMBLOCKを指定することで、共有メモリ領域のlock要求になる。
コマンドにSMBUNLOCKを指定することで、共有メモリ領域のunlock要求になる。
プロセスは、このコマンドを利用して共有メモリ領域の排他制御を行う。
2)2)2)
2)ITRONITRONITRONITRON側側側側APIAPIAPI API
OS 間インタフェースとしての共有メモリブロック方式のオブジェクトは、新規のカーネルオブジェクトとして 定義する。RTOS のタスクが共有メモリブロック方式のオブジェクトを指定してLinux 側との情報交換を行う。
Emblixの仕様で定義したAPIを説明する。
状態参照要求
【API】
ER lii_ref_smb(ID smbid, T_RSMB *pk_rsmb);
ID smbid : 共有メモリブロックの識別番号
T_RSMB *pk_rsmb : 共有メモリ状態を格納するメモリ領域のアドレスpk_rsmb 内容 ID htskid : lock している ITRON タスクのID番号
ID wtskid : 待っているITRONタスクのID番号
INT hlinuxid : lock している Linux プロセスのLinuxプロセスID INT wlinxid : 待っているLinuxプロセスのLinuxプロセスID VP address : 共有メモリアドレス
SIZE smbsz : 共有メモリサイズ(バイト)
INT linno : 対応するLinux側のドライバのマイナー番号
ATR flags : 実装依存の属性
【説明】
smbid で指定される共有メモリブロックの状態の情報を取得する。
情報は、pk_rsmb で示すアドレスからのメモリ領域内へ格納する。
lock要求
【API】
ER lii_loc_smb(ID smbid, TMO tmout);
ID smbid : 共有メモリブロックのID番号 TMO tmout : タイムアウト時間(ms 単位)
【説明】
共有メモリブロックを ITRON 側からlock要求する。
既にlock状態である場合、
自タスクがlockしている場合は、エラーを返却 他タスクがlockしている場合は、待ち状態
Linux からlockしている場合は、待ち状態とする。
unlock要求
【API】
ER lii_unl_smb(ID smbid);
ID smbid : 共有メモリブロックのID番号
【説明】
共有メモリブロックを ITRON 側からunlock要求する。
対象がlock状態でなければ、エラーを返却する。
lock状態である場合、
自タスクがlockしている場合は、lock解除する
他タスクがlockしている場合は、lock状態のまま エラーを返却
Linux からlockしている場合は、lock状態のままエラーを返却とする。
6.ハイブリッド構造の構築 6.ハイブリッド構造の構築 6.ハイブリッド構造の構築 6.ハイブリッド構造の構築
筆者は、LinuxとRTOSとのハイブリッド構造を構築するためのポイントは二つあると考えている。
① LinuxとRTOSとに二つのスケジューラがあることを意識する
② 割込み制御を工夫する
①については、システム全体のスケジューリングはRTOSのスケジューラが行うが、Linux側にもスケジューラ があることを意識する必要がある。②については、二つのOSにて割込みを使用するが、RTOSのリアルタイム性 を損なわないようにするための工夫をする必要がある。
6.1 二つの OS のスケジューラ
ハイブリッド構造を構築するにあたり、二つのOSのスケジューラが存在することを意識する必要がある。単純 に、二つのOSを実装するだけでは問題が発生する。たとえば、Linux上のプロセスAが動作している状態にあり、
プロセスBは事象を待っている状態とする。また、RTOS上のタスクXが割込みを待っている状態とする(図5)。
図5では、LinuxのスケジューラはプロセスA を実行させている状態になっており、RTOSのスケジューラは
Linux環境を動作させている状態になっている。図5の状態で、RTOS側に割込みが発生し、タスクXの待ち状態
が解除され実行状態になったとする。このとき、LinuxスケジューラはプロセスAを実行中の状態となっているが、
RTOSスケジューラはタスクXを動作させている状態になる。また、RTOS側の割込みによりLinuxのプロセス Aが動作している環境(コンテキスト)が保存される(図6)。
〔図
〔図
〔図〔図 5 5 5 5〕〕〕〕二つのスケジューラ(前段階)二つのスケジューラ(前段階)二つのスケジューラ(前段階)二つのスケジューラ(前段階)
Linux環境
プロセスA(実行状態)
RTOS環境
タスクX(割込み待ち)
Linuxカーネル
(プロセスAを実行中)
RTOSカーネル
(Linux環境を実行中)
プロセスB(事象待ち)
ここで、タスクXがLinuxの機能を使ってプロセスBの起床を行ったとする(図7)。
図7は、タスクXがLinux側のプロセスBに対して事象を通知し、LinuxのスケジューラによりプロセスBが 起床した状態を示す。この状態は、RTOSのスケジューラにとっては、プロセスBはタスクXの延長で動作して いると認識することになる。図7の状態で、RTOSスケジューラによりLinux環境を動作していたタスクに制御を 渡すとした場合、スケジューラは、保存していたプロセスAのコンテキストを復旧することになる(図8)。Linux の動作環境はプロセスBが動作する環境となっているので、プロセスAは正常な動作にはならない。
〔図〔図
〔図〔図 7777〕〕〕〕二つのスケジューラ(二つのスケジューラ(二つのスケジューラ(二つのスケジューラ(LinuxLinuxLinuxLinux側に事象通知)側に事象通知) 側に事象通知)側に事象通知)
〔図〔図
〔図〔図 6 6 6 6〕〕〕〕二つのスケジューラ(二つのスケジューラ(二つのスケジューラ(二つのスケジューラ(RTOSRTOSRTOSRTOS側の割込み発生)側の割込み発生)側の割込み発生)側の割込み発生)
Linux環境
プロセスA(実行状態)
RTOS環境
タスクX(実行状態)
Linuxカーネル
(プロセスAを実行中)
RTOSカーネル
(タスクXを実行中)
Linux環境の コンテキスト保存 プロセスB(事象待ち)
RTOS側の割込み
起床
Linux環境
プロセスA(実行可能状態)
RTOS環境
タスクX(実行状態)
Linuxカーネル
(プロセスBを実行中)
RTOSカーネル
(タスクXを実行中)
プロセスB(実行状態)
事象通知
上記の例では、RTOSスケジューラがLinuxの動作環境が変化したことを認識していないために不都合が発生し ている。ハイブリッド構造においてRTOSスケジューラが全体のスケジューリングを行うとした場合、割込みも含
めて Linuxの動作環境の変化をLinuxタスク内での出来事であるようスケジューリングする。そのため、Linux
のプロセスやRTOSのタスクは、RTOSスケジューラの認識せずに相手OSの動作環境を変えるような操作をしな いようにする。
割込みについては、Emblixで作成した仕様に準拠するとLinuxの割込みはLinuxタスクの動作中にしか発生し ないため、スケジューリングはそれほど困難ではない。
〔図〔図
〔図〔図 8888〕〕〕〕二つのスケジューラ(二つのスケジューラ(二つのスケジューラ(二つのスケジューラ(LinuxLinuxLinuxLinux動作環境への切替え)動作環境への切替え)動作環境への切替え)動作環境への切替え)
Linux環境
プロセスA(実行可能状態)
RTOS環境
タスクX(実行状態)
Linuxカーネル
(プロセスBを実行中)
RTOSカーネル
(Linux環境を実行中)
プロセスB(実行状態) 切替え
6.2 Linux の動作環境
ハイブリッド構造を構成するにあたり、Linux環境を動作するプログラム全体をRTOSの一つのタスクとして認 識させるのがもっとも簡単である。Linuxの動作環境を一つのタスクとして認識させる方法を示す。
① はじめにRTOSシステムが立ち上がり、RTOSシステムの一つのタスクがLinuxをブートする(図9)。
② はじめにLinuxが立ち上がり、Linuxの初期化時にRTOSシステムを起動する。RTOSシステムに登録して いる一つのタスクがLinux環境を動作させる(図10)。
①において、LinuxをブートするとRTOSシステムでハードウェアを設定してもLinuxで再設定される。RTOS システムは、ハードウェアの設定を再び行う必要がある。②において、LinuxからRTOSシステムを起動する際に コンテキストを保存する。RTOS システムに登録している一つのタスクでそのコンテキストを復旧することで、
RTOSカーネルは、Linuxの動作環境を一つのタスクとして認識する。
〔
〔
〔
〔図図図図 9999〕〕〕〕LinuxLinuxLinuxLinux動作環境をタスクにする(動作環境をタスクにする(RTOS動作環境をタスクにする(動作環境をタスクにする(RTOSRTOSRTOSが先)が先)が先)が先)
〔図
〔図
〔図〔図 10101010〕〕〕Linux〕LinuxLinuxLinux動作環境をタスクにする(動作環境をタスクにする(動作環境をタスクにする(動作環境をタスクにする(LinuxLinuxLinuxLinuxが先)が先) が先)が先)
Linux 動作環境 RTOS 動作環境
タスク
起動 プロセス
Linux カーネル
ブート RTOS カーネル
タスク
Linux 動作環境 RTOS 動作環境
タスク
復旧 プロセス
Linux カーネル
ブート RTOS カーネル
タスク コンテ
キスト 保存
起動
6.3 割込み制御
ここでの割込み制御とは、二つの処理のことをいう。
① 割込みハンドラにおける処理
② RTOSのリアルタイム性を損なわないようにするための処理
①については、割込みコントローラからの割込み事象に対する処理になる。具体的には、割込みの発生が、RTOS 側で使用する割込みの要因であるか否かをチェックし、RTOS側が使用する割込みである場合は、RTOS側に制御 を渡す。それ以外は、Linuxの割込み処理を行う。
②については、Emblixの仕様で規定されている処理優先順位にしたがうようにLinux割込みを制御する。具体 的には、Linuxタスク以外のRTOSシステムが動作している間はLinux側の割込みが発生しないように割込みを マスクする。Linuxタスクが動作する際に、Linux側の割込みが発生するように割込みのマスクを解除する。また は、割込みを仮想化し、リアルタイム処理中の割込みが発生した場合はいったん保留し、通常処理時に割込み処理 を行う方法もある。
1)割込み処理 1)割込み処理1)割込み処理 1)割込み処理
RTOS側で割込みを使用する場合は、割込みハンドラの登録を行い、RTOSはその割込み番号と割込みハンドラ の情報を保持する。割込み発生時にLinuxではその割込み要因を検索する処理が実行する。ハイブリッド構造を構 築する場合は、その割込み要因を検索する処理で、RTOS側の割込みであることのチェックを優先する。RTOS側 の割込みである場合は、RTOS側の割込みハンドラに制御を渡す。Linuxでの割込みハンドラ処理を図11に示す。
図11の※1〜※3にRTOS側の割込み要因のチェックを入れた場合について記述する。
※1でチェックする場合は、比較的短い時間でRTOS側の割込み要因で あるかのチェック処理を行うことができる。ただし、※2で行う処理と同 じような処理を行うことになる。
※2でチェックする場合は、RTOS 側に登録されている割込み番号と
Linux側に登録されている割込み番号を参照していくことになる。RTOS
側の割込みである場合は、Linuxが保存したコンテキストをRTOS側が保 存するコンテキスト情報に変換して、RTOS 側に制御を渡すようにする。
Linuxが保存するコンテキスト情報とRTOSが保存するコンテキスト情報
とを同じ形式にすることで、割込み処理のオーバヘッドは小さくなる。
※3でチェックする場合が、一番実装が楽である。Linuxの割込み要因 のチェック処理でチェックされた割込み番号が RTOS 側のものかLinux 側のものかを判断すればよい。RTOS側の割込みの場合は、※2と同様に コンテキストの変換を行って、RTOS側に制御を渡す。
〔図〔図〔図
〔図11111111〕〕〕〕LinuxLinuxLinuxLinux割込みハンドラ処理割込みハンドラ処理 割込みハンドラ処理割込みハンドラ処理
割込みハンドラ
コンテキスト保存
割込み要因検索
do_irq
※1
※3
※2
2)割込み制御 2)割込み制御2)割込み制御 2)割込み制御
RTOS側のリアルタイム性を損なわないようにするために、Linux側の割込みについて制御を行う必要がある。
Linux側の割込み処理をRTOSのタスクの優先順位より低く定義した場合、Linuxタスクが動作中のみLinux側
の割込み処理が実行するようにする。具体的には、Linuxタスク以外の RTOS 側の動作環境が実行している間は
Linux側の割込みをマスクするのが簡単である。
Linux側の割込み処理をRTOSのタスクの優先順位より高く定義した場合は、処理が複雑になる。具体的には、
RTOSのタスクがRTOSカーネルに要求を行った時点でLinux側の割込みをマスクする。RTOSカーネルからタ スクに戻るときにLinux側の割込みのマスクを解除する。RTOS側のタスク実行中にLinux側の割込みが発生し た場合は、Linux側の割込み処理が終了したら、RTOSスケジューラに制御を戻し、割込まれたRTOSタスクに制 御がわたるようにする必要がある。
7.リア 7.リア 7.リア
7.リアルタイム ルタイム ルタイム ルタイム OS OS OS OS とハイブリッド構造 とハイブリッド構造 とハイブリッド構造 とハイブリッド構造
Emblixでの仕様は、μITRON仕様に準拠したOSを前提としているが、ハイブリッド構造はどんなRTOSでも
同じように構築できる。ただし、すべてのRTOSがハイブリッド構造を構築できるとはかぎらない。リアルタイム OS(RTOS)がもつ機能や方式によりハイブリッド構造の構築が困難な場合がある。
サービスコールがソフトウェア割込みの場合
RTOSのサービスコールがソフトウェア割込みの場合、Linuxと重複するため、機能コードが重複しないように する必要がある。
サービスコールがソフトウェア割込みを使用しないRTOSであることが望ましい。
RTOSがバイナリ提供の場合
ハイブリッド構造を構築するにあたり、RTOS のスケジューラや割込み制御の一部を改変する必要があるため、
RTOSがバイナリ提供ではそれができない。ソースが改変できるRTOSであることが望ましい。
RTOSがMMUを使う場合
LinuxでもMMUを使用するため、MMU制御が複雑になる。
RTOSは、スーパバイザモードで動作するものが望ましい。
CPU対応
当然ながら、RTOSが実行CPUのアーキテクチャに対応している必要がある。
8.ハイブリッド構造の実装時の注意 8.ハイブリッド構造の実装時の注意 8.ハイブリッド構造の実装時の注意 8.ハイブリッド構造の実装時の注意
ハイブリッド構造を実装する場合、注意すべき点をいくつか記述する。
二つのスケジューラ
Linux側とRTOS側とで二つのスケジューラがある。RTOS側のタスクがRTOSのスケジューラが関知せずに
Linux側の動作環境が変化するような要求を行わないようにする。RTOSのスケジューラが全体のスケジューリン
グを行うようにして、割込み処理も含めたLinux側の動作を1タスクとして制御すると実装が容易になる。
コンパイラ
RTOSのシステムを特定の番地に配置するのであれば、OS間でのインタフェースを考慮さえすれば、RTOSの システムを構築するためのコンパイラは、実行CPUに合ったものでよい。RTOSのシステムをLinuxと一緒にリ ンクするとした場合、RTOSはGNUコンパイラでコンパイルできるようになっている必要がある。
標準関数
RTOSシステムは、GNUの開発環境からすると、スーパバイザモードでの動作という観点から、カーネルの開 発と同等になる。RTOSシステムでは、C言語の標準関数が利用できない場合があるので、注意する必要がある。
シンボルの重複
RTOSシステムをLinuxシステムと一緒にリンクする場合、シンボルの重複に注意する必要がある。
ICE
ICEはJ-TAG対応のものが望ましい。ROMエミュレータ型のICEでは、デバッグモニタをダウンロードして
割込みの処理を行う。デバッグモニタは、一般に割込みを受け付けるとカレントスタックにレジスタを保存する。
Linux側のプロセスが実行しているときに割込みが発生し、そのスタックにレジスタを保存してしまうと、そのス
タックがページ境界を越えてしまった場合、MMUのページ例外が発生する。割込み処理(割込み禁止状態)での ページ例外は、CPUによってはリセットが発生する。また、ICEは、GNUコンパイラに対応していることが望ま しい。
9.実装例 9.実装例 9.実装例 9.実装例
筆者が行った、LinuxとμITRON仕様準拠のRTOSでのハイブリッド構造の実装例を説明する。実装は、Emblix で策定した仕様にしたがって行った。筆者が実装を行った環境を以下に示す。
Linux : Hard Hat Linux 2.0
μITRON : 自社製μITRON3.0仕様準拠 CPU : VR4122
筆者は、ハイブリッド構造を実装するポイントとしては、次の三つがあると思っている。
初期化処理
割込み処理/割込み制御 OS間インタフェース
9.1 初期化
Linuxでの初期化が終了し、実際のシステムを起動する前に、ITRONシステムを起動する。
静的な領域に、ITRONシステムを起動する際のCPUレジスタを保存する。ITRONシステムには、Linuxタス ク(システムでいちばん優先度が低いタスク)を登録している。ITRON システムが起動すると各種カーネルオブ ジェクトの生成を行い、高優先度のタスクが実行する。高優先度タスクが待ち状態になると、Linuxタスクが実行 する。
Linuxタスクでは、先に保存していたCPUレジスタを復旧し、Linuxの処理に戻り、Linuxシステムが起動す
る。この時点で、Linuxシステムの動作環境は、ITRONカーネルの1タスクとして認識される。Linuxタスクに は生成時に属性を付けており、この属性はITRONカーネルのスケジューラにより参照される。VR4122で実装し たソースをリスト1、およびリスト2に示す。
〔リスト
〔リスト
〔リスト
〔リスト1111〕〕〕〕ITRONITRONITRONITRONシステム起動前処理システム起動前処理 システム起動前処理システム起動前処理
/**************************************
* start_itron
* It changes mode from Linux to ITRON *
*/
.text
NESTED(start_itron, PT_SIZE, ra) .set at
.set noreorder
# *** disable interrupt addi sp, sp, -4
sw ra, 0(sp) jal _ELX_dis_int nop
;
# *** save context
;
sw t1, -0x04(sp) # push without sp move la t1, context_reg
;
.set noat
sw $1, PT_R1(t1) .set at
sw $2, PT_R2(t1) sw $3, PT_R3(t1) sw $4, PT_R4(t1) sw $5, PT_R5(t1) sw $6, PT_R6(t1) sw $7, PT_R7(t1) sw $8, PT_R8(t1)
lw t0, -0x04(sp) # t0 = $8
sw t0, PT_R9(t1) # pop without sp move sw $10, PT_R10(t1)
sw $11, PT_R11(t1) sw $12, PT_R12(t1) sw $13, PT_R13(t1) sw $14, PT_R14(t1) sw $15, PT_R15(t1) sw $16, PT_R16(t1) sw $17, PT_R17(t1) sw $18, PT_R18(t1) sw $19, PT_R19(t1) sw $20, PT_R20(t1) sw $21, PT_R21(t1) sw $22, PT_R22(t1) sw $23, PT_R23(t1) sw $24, PT_R24(t1) sw $25, PT_R25(t1) sw $26, PT_R26(t1) sw $27, PT_R27(t1) sw $28, PT_R28(t1) sw $30, PT_R30(t1)
la t0, LOI_LINUX_CONTINUE_HERE sw t0, PT_R31(t1)
mfc0 t0, CP0_STATUS nop #
nop # CP0 hazard nop #
sw t0, PT_STATUS(t1)
;
sw sp, loi_init_sp
# Save ICU & cli (Linux -> ITRON) jal loi_switchto_itron nop
la sp, loi_itron_stack # ITRON stack in kernel initialize
addi sp, sp, SIZ_STACK
j ITRON_main # to ITRON nop
# **************
#
# Here is ITRON start up rutine
#
# **************
LOI_LINUX_CONTINUE_HERE:
lw ra, 0(sp) addi sp, sp, 4
;
jr ra nop
END(start_itron)
/**************************************
* Symbol Table *
*/
.data
.align 4
EXPORT(context_reg)
.rept PT_SIZE # register saving area .byte 0x40
.endr
EXPORT(loi_init_sp) # Linux SP .word 0
EXPORT(loi_itron_stack) .rept SIZ_STACK .byte 0x40 .endr
CPUレジスタの保存 割込み禁止
ITRONシステム
の起動
Linux側に制御を戻す
.text .align 4 EXPORT(XTASK_linux)
la t0, context_reg # static area
/* restore register */
.set noat
lw $1, PT_R1(t0)
.set at
lw $2, PT_R2(t0) lw $3, PT_R3(t0) lw $4, PT_R4(t0) lw $5, PT_R5(t0) lw $6, PT_R6(t0) lw $7, PT_R7(t0)
# nop R8 (t0) restore later
# nop R9 (t1) restore later lw $10, PT_R10(t0) lw $11, PT_R11(t0) lw $12, PT_R12(t0) lw $13, PT_R13(t0) lw $14, PT_R14(t0) lw $15, PT_R15(t0) lw $16, PT_R16(t0) lw $17, PT_R17(t0) lw $18, PT_R18(t0) lw $19, PT_R19(t0) lw $20, PT_R20(t0) lw $21, PT_R21(t0) lw $22, PT_R22(t0) lw $23, PT_R23(t0) lw $24, PT_R24(t0) lw $25, PT_R25(t0) lw $26, PT_R26(t0) lw $27, PT_R27(t0) lw $28, PT_R28(t0)
# nop R29(sp) restore from loi_init_sp later lw $30, PT_R30(t0)
lw $31, PT_R31(t0)
lw t1, PT_STATUS(t0) mtc0 t1, CP0_STATUS
nop #
nop # CP0 hazard
nop #
;
# restore work registers
lw $9, PT_R9(t0) # t1 lw $8, PT_R8(t0) # t0
;
lw $29, loi_init_sp # sp
jr $31 # ra
nop
;
CPUレジスタの復帰
リスト1の
LOI_LINUX_CONTINUE_HERE にジャンプ
Linuxタスクの起動番地
〔リスト
〔リスト
〔リスト
〔リスト2222〕〕〕〕LinuxLinuxLinuxLinuxタスクになるタスクになるタスクになるタスクになるタスクの起動処理タスクの起動処理タスクの起動処理タスクの起動処理
9.2 割込み処理/割込み制御
1)割込 1)割込1)割込
1)割込みの処理みの処理みの処理みの処理
ITRONシステムでは、システム起動時にサービスコールdef_intにて割込みハンドラの登録を行う。カーネル
はdef_intで指定される割込み番号とハンドラアドレスを割込み管理テーブルに登録する。筆者が実装した割込 みの振分け処理は、Linuxの関数do_irqに組み込んだ。
実装したVR4122での割込み要因のチェックが多段になっており、ITRON側の割込みを優先的にチェックする ようにすると、かえって無駄な処理が増えてしまう。そのため、LinuxのCPUに対して実装された割込み要因チ ェックをほとんどそのままとし、検索結果からITRON側の割込みであるかどうかを判断するようにした。VR4122 で実装したソースをリスト3、およびリスト4に示す。
2)割込み制御 2)割込み制御2)割込み制御 2)割込み制御
Emblixの仕様にある優先順位にしたがうために、Linux側の割込みのマスク/マスク解除を行っている。
Linuxタスク動作中に、ITRON側の割込み発生時、Linux側の割込みマスク状態を保存し、Linux側の割込 みをマスクする。
LinuxタスクがITRONのサービスコールを発行した場合、ITRONのカーネル処理を行う際にLinux側の割 込みマスク状態を保存し、Linux側の割込みをマスクする。
Linuxタスクに制御を渡す場合、Linux側のマスク状態からLinux側の割込みのマスクを解除する。
割込み復帰時にLinuxタスクに戻る場合、Linux側のマスク状態からLinux側の割込みのマスクを解除する。
Linux側の割込みのマスク/マスク解除処理は、以下のように行っている。
割込みのマスク
現状の割込みのマスク状態を取得し、情報として保存する。
ITRON側で使用する割込みのマスク状態を残し、それ以外の割込み(Linuxで使用する割込み)をマスクする。
割込みのマスク解除
現状の割込みのマスク状態を取得し、ITRON側で使用する割込みのマスク状態の情報を作成する。
先に情報として保存している割込みマスク状態からLinux 側の割込みのマスク状態の情報を抜き出し、それと
ITRON側のマスク状態の情報を加味し、割込みマスク情報とする。
#
# interrupt entry
#
.text
.set noreorder
NESTED(vr4122_handle_int, PT_SIZE, ra) .set noat
# Stack Save for Linux SAVE_ALL CLI
.set at
.set noreorder
/*
* Get the pending interrupts
*/
mfc0 t0, CP0_CAUSE mfc0 t1, CP0_STATUS andi t0, 0xff00 and t0, t0, t1
andi t1, t0, CAUSEF_IP7 # timer interrupt beqz t1, 1f
li a0, 7
jal ll_timer_interrupt # for Linux only move a1, sp
j ret_from_irq nop
1:
andi t1, t0, 0x7800 # check for IP3-6 beqz t1, 2f
andi t1, t0, CAUSEF_IP3 # check for IP3 bnez t1, handle_it
li a0, 3
andi t1, t0, CAUSEF_IP4 # check for IP4 bnez t1, handle_it
li a0, 4
<中略>
3:
andi t1, t0, CAUSEF_IP0 # check for IP0 bnez t1, handle_it
li a0, 0
andi t1, t0, CAUSEF_IP1 # check for IP1 bnez t1, handle_it
li a0, 1
j spurious_interrupt nop
コンテキストの保存
割込み要因の検索 割込みハンドラ入り口
〔リスト
〔リスト
〔リスト
〔リスト3333〕割込みハンドラ〕割込みハンドラ〕割込みハンドラ〕割込みハンドラ
# a0 : interrupt cause No.
#
# interrupt entry
# .text
;
;
NESTED(do_IRQ, PT_SIZE, ra)
CLI # disable interrupt nop
;
# GET A CAUSE OF INTERRUPT
la t1, YMON_exc_tbl # top address of vector table move t0, a0
sll t0, 2 # * 4 (Align)
addu t1, t1, t0 # a0(paramater) : IRQ No.
lw t2, 0(t1) # get vector handle
beqz t2, _undef_int # handle is undefined -> brunch nop
;
# SWITCHING TO ITRON, here
;
# save kernel register -> sp is same point as it in interrupt moment sw k0, PT_R26(sp)
sw k1, PT_R27(sp)
;
addi sp, sp, -0x0C sw t0, 0x00(sp) sw t1, 0x04(sp) sw ra, 0x08(sp)
;
# SWITCH TO ITRON *****
lw t1, YMON_run # Is task Linux ?
beqz t1, INT_FROM_ITRON # YMON_run == 0 -> XMON_idle: Non-Linux nop
lw t1, TCB_ATR(t1) #
andi t1, t1, TA_DIN # Linux Task(DIN Atribute) ? beqz t1, INT_FROM_ITRON
nop
jal loi_switchto_itron # mask ICU, here nop
INT_FROM_ITRON:
# SWITCH TO ITRON *****
jalr t2 # call handler nop
;
lw t0, 0x00(sp) lw t1, 0x04(sp) lw ra, 0x08(sp) addi sp, sp, 0x0C
CLI # disable interrupt
;
j XMON_int_start # to ITRON
nop #
;
;
# UNDEFINED INTERRUPT (SWITCHING TO LINUX) _undef_int:
;
# a0: interrupt cause No., here
;
jal do_IRQ_bh # Linux native IRQ rutine
〔リスト
〔リスト
〔リスト
〔リスト4444〕〕〕〕do_irq
ITRONスケジューラの呼び出し
ITRONが割込みでない場合、Linuxの割込み
ITRONの割込み判定
ITRONを割込みモードにする処理
Linuxタスク動作中の場合、割込みをマスク
ITRONハンドラの呼び出し
9.3 OS 間インタフェース
OS間インタフェースを実装するのにITRONのサービスコールを利用している。Linuxの動作環境は、ITRON からすればタスク(Linuxタスク)として動作しているので、ITRONのサービスコールが発行できる。
OS間インタフェースを、実装ではITRONのサービスコールを使い、ITRONがもつ機能を利用している。OS 間インタフェースにITRONのサービスコールを使用するとした場合、Linux側の待ち状態をいかに実現するかと いう問題がある。
Linuxタスクは一つのタスクとして実行している。LinuxタスクがITRONのサービスコールを使って待ち状態
になってしまうと、ITRONのスケジューラはLinuxタスクに対し制御を渡さなくなるため、Linuxのシステム全 体が停止することになる。実装では、待ち状態になる可能性がある要求については、Linuxのデバイスドライバか らポーリングの要求を一定周期で要求するようにした。OS間インタフェース機能であるFIFO方式と共有メモリ ブロック方式の実装について説明する。
1)
1)1)
1)FIFOFIFOFIFOFIFO方式方式方式方式
FIFO 方式を実装する際に、ITRON がもつ機能であるメールボックス機能とメモリプール機能を利用した。
LinuxからITRONへ、ITRONからLinuxへの二つの経路のために、二つずつメールボックスとメモリプールを
ITRON側で生成している(図12)。LinuxのデバイスドライバおよびITRON側のAPIでは、送信要求において
メモリプールからメモリブロックを取得し、メモリブロックにデータをコピーし、メールボックスに送信要求を行 うようにしている。
受信要求では、メールボックスからメッセージ(メモリブロック)を受信し、メモリブロック内にあるデータを ユーザバッファにコピーして、メモリブロックをメモリプールに返却する。Linuxのデバイスドライバでは、メモ リプールからのメモリブロックの取得要求およびメールボックスからのメッセージ受信要求は、ポーリング要求を 行っている。
〔図〔図
〔図〔図12121212〕組込んだ〕組込んだ〕組込んだ〕組込んだOSOSOSOSののののAPIAPI(APIAPI((1111)( )))
メールボックス メモリプール メモリプールメモリプール メモリプール
Linux ITRON
FIFO方式 デバイス ドライバ
FIFO方式 API関数
(LinuxからITRONへの経路)
メモリブロック取得 メモリブロック返却
メッセージ送信 メッセージ受信
メッセージ受信 メッセージ送信
2)共有メモリブロック方式 2)共有メモリブロック方式2)共有メモリブロック方式 2)共有メモリブロック方式
共有メモリブロック方式を実装する際に、ITRON がもつ機能であるセマフォ機能を利用した。共有メモリブロ ックを排他制御するために、セマフォをITRON側で生成している(図13)。
LinuxのデバイスドライバおよびITRON側のAPIでは、lock要求においてセマフォの取得要求を行っている。
unlock要求では、セマフォの返却要求を行っている。Linuxのデバイスドライバでは、セマフォの取得要求は、
ポーリング要求を行っている(図13の破線)。
9.4 ITRON 仕様準拠カーネルについて
実装する際に使用したμITRON 仕様に準拠したカーネルは筆者の会社で開発したものであるので、ソースの改 変ができる。このITRONカーネルに対し、Linuxタスクを特別に扱うように改変した。
このITRONカーネルのサービスコールは、ソフトウェア割込みを使用していない。サービスコールの関数内で
カーネルが行うべき処理をし、自タスクの状態が変化する(実行状態以外になる)場合に、スケジューラを呼び出 すようになっている。
また、タスク用に保存するコンテキストは、Linuxが割込み発生時にスタック中に保存する形式と同じにしてい
る。Linuxの割込み処理と同じコンテキストの形式にすることで、割込み発生時にLinuxの処理で保存するコンテ
キストをITRONカーネルが保存するコンテキストに変換する必要がなくなり、オーバヘッドの削減になる。
〔図〔図
〔図〔図1313〕組1313〕組〕組〕組込んだ込んだ込んだ込んだOSOSOSOSののののAPIAPIAPIAPI((((2222))) )
Linux
共有メモリ ブロック方式 デバイス ドライバ
ITRON
共有メモリ ブロック方式 API関数
セマフォセマフォセマフォ セマフォ
セマフォ取得 セマフォ取得
セマフォ返却 セマフォ返却