こんにちは、ナナです。
リアルタイムOSが搭載されたシステムではタスクという概念でプログラムが動作します。
タスクというものをイメージとしてどのように捉えるかは、リアルタイムOSを知るうえで非常に大事なことです。まずはタスクをしっかりとイメージできるようにしましょう。
本記事では次の疑問点を解消する内容となっています。
では、順に解説していきましょう。
ITRON仕様のおけるタスクの定義と理解するためのイメージ
ITRON仕様書のPDFを開いて「3.1 基本的な用語の意味」を見てみましょう。タスクという用語は次のように定義されています。
「プログラムの平行実行の単位をタスクと呼ぶ」
リアルタイムOS及びITRON仕様を理解する上で、「タスク」というものを知ることがすべての始まりです。このタスクを中心にITRONはシステムを動作させます。まずはタスクの概念を学びましょう。
タスクを捉えるイメージ
プログラムの平行実行の単位と言われてもなかなかイメージがつかみづらいですね。
「タスク」とは翻訳すると「仕事」といった意味です。リアルタイムOSを解説したサイトではやはりタスクを仕事として解説しているものも多いです。
しかし、私がタスクというものに対して抱いているイメージは異なります。
タスクとはプログラムを動かす労働者である
これが私のタスクに対するイメージです。
プログラムが動くとは労働者が働くこと
皆さんはこれまでにC言語入門編やマイコン入門編においてたくさんのプログラムを作成してきました。例えば次のようなプログラムですね。
#include <stdio.h>
int main(void)
{
long calc = 0;
calc = 100 + 200;
printf("結果:%d", calc);
return 0;
}
このようなプログラムをステップ実行を行いながら、1行1行プログラムを動作させたことがあるでしょう。
このプログラムが1行ずつ動くということが、労働者がプログラムの処理内容を実施していると捉えます。これがタスクのイメージです。
C言語においてはmain関数からプログラムが動き出します。
つまり、プログラムが動き出す時に労働者が1人用意され、その労働者に対して「君はmain関数という仕事を実施してくれたまえ!」と指示がされて動いているということになります。
このようにプログラムを「仕事内容」として捉え、タスクを「仕事を実施する労働者」として捉えるイメージです。このイメージがタスクというものを理解する上で大事なイメージです。
リアルタイムOSを搭載しないプログラムの課題
リアルタイムOSを搭載しないシステムでは、そもそもタスクという概念はありません。
それでもmain関数を実施する労働力は用意されるのですから、あえて言うなれば1人のタスク(シングルタスク)で動作しているとも言えます。
それではシングルタスクのシステムにおける問題とはどのような場合に起こるのかを考えてみましょう。
ソフトウェアシステムとは様々なミッションがプログラムという形で作られ動いていきます。これから2つのミッションを作るうえでシングルタスクの難しさを明確化していきます。
LED点滅のミッション
プログラムというのは順次処理が基本であり、記述された順に上から下へ実行されます。
例えば現時点の次のプログラムを見てみましょう。LEDが点滅しているのはタスクがこのミッションを実行しているからです。
main.c
//------------------------------------------------
// 概 要: MAINタスク
//------------------------------------------------
void MAIN(VP_INT exinf)
{
while(1)
{
Led_setLight(D_LED_KIND_ORANGE, D_LED_LIGHT_ON);
Led_setLight(D_LED_KIND_GREEN, D_LED_LIGHT_OFF);
dly_tsk(1000);
Led_setLight(D_LED_KIND_ORANGE, D_LED_LIGHT_OFF);
Led_setLight(D_LED_KIND_GREEN, D_LED_LIGHT_ON);
dly_tsk(1000);
}
return;
}
dly_tsk関数とはITRON仕様の関数であり、指定時間(ミリ秒)だけタスクの動きを停止させる関数です。このように順番に決められた作業を忠実に行うプログラムは書きやすいですね。
音を鳴らすミッション
では、次に別のミッションを作ってみましょう。2秒ごとに「ピッピッ」というビープ音を2回出力するミッションが必要になったとします。
main.c
//------------------------------------------------
// 概 要: MAINタスク
//------------------------------------------------
void MAIN(VP_INT exinf)
{
while(1)
{
int i;
// 400msの時間ビープ音を鳴らす
for (i=0 ; i < 2 ; i++)
{
Spk_start(E_SPK_SCALE_DO);
dly_tsk(100);
Spk_stop();
dly_tsk(100);
}
// 2000ms - 400ms を待機
dly_tsk(1600);
}
return;
}
MAIN関数の中身をこのミッションに変更してみましょう。皆さんも書き換えて動かしてみてください。2秒間隔でビープ音が出力されるのがわかるはずです。
2つのミッションを同時に成立させるには
それでは皆さんに問題です。この2つのミッションを同時に成立するプログラムを作ってください。
- 「1秒ごとにLEDを点滅する」
- 「2秒ごとにビープ音を出力する」
考えて答えが出た方、5分以上考えて答えが出なかった方は解答を開いて見てみてください。
申し訳ないですが、解答は作ってありません。
皆さん考えてわかったと思いますが、このプログラムを作るのかなりしんどいですよね。私も作るのしんどいです。
ここで知ってい頂きたいのは2つ以上の時間制約が異なるミッションを同時並行で行うことの難しさです。
シングルタスクで処理を行うということは、1人の人が複数の仕事を同時並行でミッションを遂行できるようにしなければならないということなのです。
これこそがシングルタスクの課題なのです。2つのミッションでさえしんどいのに、もっと多くのミッションが必要な場合にシングルタスクでは対処しきれないのです。
リアルタイムOSにおけるマルチタスク機能こそがこの問題を解決するのです。
タスクとスレッドとプロセスの関係
少しOSに関しての知識を持っている方は「スレッド」や「プロセス」といった用語を聞いたことがあるかもしれません。
OSが搭載されたシステムにおいてよく使用される「タスク」「スレッド」「プロセス」に関して違いを解説しておきましょう。
タスク
リアルタイムOSにおける並行処理の実行単位を示す用語。システム内に複数のタスクを存在させることをマルチタスクと呼びます。
スレッド
WindowsやLinuxにおける並行処理の実行単位を示す用語。つまり、ITRONにおけるタスクと同じ意味です。システム内に複数のスレッドを存在させることをマルチスレッドと呼びます。
プロセス
WindowsやLinuxにおいて、アプリケーションの実行単位を示す用語。例えばExcelやWordといったアプリケーションを起動すると、それぞれが別のプロセスとして起動することになります。
このような複数のアプリケーションを同時に起動できる仕組みをマルチプロセスと呼びます。プロセスの中には複数のスレッド所属させることができます。
ITRONにはプロセスという概念は存在しません。それはシステムにおいてアプリケーションを1つしか持つことができないため、プロセスという単位を持つ必要がないからです。
プロセスとスレッドの違い
プロセスとスレッドの大きな違いはメモリ空間を共有するかしないかです。WindowsやLinuxではプロセスという単位でメモリを独立管理するため、プロセスが異なると他のプロセスのメモリにはアクセスできません。
例えばExcel内で動作しているプログラムからWord内で定義されている関数を呼び出すことはできないのです。もしもそんなことができたとしたら、悪意のあるプログラムによって様々なアプリケーションの動作を破壊することが可能になってしまうことでしょう。
これはWindowsやLinuxは仮想メモリという機構を利用し、プロセスという単位でメモリ保護を行っているのです。
これに対し、同一プロセス内に存在する複数のスレッドはメモリを共有しています。そのため、プロセス内で定義された関数やグローバル変数に対して、各プロセス内のスレッドは自由にアクセスすることができます。