カーネル内タスク管理

base version : v0.1.0

各種初期化が終わると、カーネルはタスク実行モードに入る。

カーネル内で処理すべきタスクをコールバック関数としてTaskCtrl(カーネルタスク管理クラス)に登録する事で、複数のタスクを順番に処理する事ができる。また、処理を別のCPUコアに投げる事もできる。

BSD Kernelのcalloutをイメージしてもらうと分かりやすいかもしれない。プロセスの事ではないので、注意。

カーネルタスクの使用用途としては、あるデバイスのI/O処理を行う関数があったとして、割り込みハンドラ内でその関数をTaskCtrlに登録する事で、割り込みハンドラを抜けた後で、TaskCtrlに自動的にI/O処理コールバック関数を呼び出してもらう、という例がある。

TaskCtrl

TaskCtrlクラスはRaph Library内に定義(→Raph_Library/rlib/task.h)、実装(→Raph_Library/rlib/task.cc)されている。

TaskCtrlクラス自体はTaskクラスを登録、削除するだけのシンプルなインターフェースだが、殆どの場合、TaskCtrlを直接呼び出す事は稀で、FunctionalQueueやCalloutを通じて呼び出す事が多い。

各CPUコアは初期化が終わるとTaskCtrl::Runを呼び出す。(→kernel/main.cc

TaskCtrl::Run(→Raph_Library/rlib/task.cc#L64)は呼び出されるとタスクキューを読み込み、実行できるものから順番に実行していく。実行されるタスクが無くなった場合、コアをhltし、他のコアから叩き起こされる(→Raph_Library/rlib/task.cc#L303)まで眠りにつく。

Callout

Calloutクラスはある程度時間を置いてから実行したいタスクを登録する際に使う。Callout::SetHandlerで何us後に実行するか指定する。(→Raph_Library/rlib/task.h

FunctionalQueue

恐らく多くの場合、タスクの登録はFunctionalQueueを通して行われる事となる。(→Raph_Library/rlib/queue.h

FunctionalQueueは、関数登録が可能なキュー(→基本的なデータ構造<執筆中>)で、関数を登録しておくと、キューにオブジェクトがpushされると、登録された関数を呼び出す。

Polling

カーネル開発においてポーリングを用いるのはあまり良い設計とは言えないが、試験的実装や性能向上を目的としてポーリングせざるを得ないケースは存在する。

ポーリングの一番簡単な方法はwhileループを回してしまう事だが、これだけは絶対にしない事。

whileループを回してしまうと、そのループがCPUを独占してしまい、そのCPU上で他のカーネルタスクを実行する事ができなくなってしまう。これは、ループによってTaskCtrlに処理が戻らないため、TaskCtrlが次のタスクを実行する事ができないからである。

Raph KernelではTaskCtrlに処理を返しつつ、ポーリングを実現する手段としてPollingクラスを用意している。(→Raph_Library/rlib/polling.h)実用的にはPollingFuncクラスを使うのが良い。

Initでコールバック関数を設定した後、Registerを呼ぶと、他のカーネルタスクを邪魔する事なく、永遠に処理を回し続ける事ができる。

くどいが、コールバック関数でwhileループを回さない事。TaskCtrlに処理が戻らなくなってしまう。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中