Weitere ähnliche Inhalte
Ähnlich wie 【学習メモ#9th】12ステップで作る組込みOS自作入門 (20)
Kürzlich hochgeladen (10)
【学習メモ#9th】12ステップで作る組込みOS自作入門
- 5. 優先度
● 組込みのOSでは一般的に優先度をベースにスケ
ジューリングが行われている
● 優先度の高いスレッドが常に動作する
- 6. スレッドの状態
● ここまでのプログラムのスレッドは常に「動作
可能」の状態。常に動いているってこと
● これだと複数スレッド間で同期的な動作をさせ
られない
– あるスレッドが特定の処理を行うまで別スレッドが
待ち合わせする、といったことができない
● そこでスレッドに「待ち」という状態を追加す
る
– スレッドを待ちにするシステム・コールを作る
● 待ち状態にするにはレディー・キューからス
レッドを抜けばいい
- 7. スレッドにおける状態の呼び名
● スレッドが「待ち」状態に入ることをスリープ
やウェイティングと呼ぶ
● スレッドがキューに繋がって動作可能の状態を
レディーと呼ぶ
● スリープ状態のスレッドをレディー状態に戻す
ことをウェイクアップと呼ぶ
● 動作中のスレッドはアクティブやランニングな
どと呼ぶ
● このように、スレッドにはレディーとスリープ
の2つの状態が存在する
- 8. 優先度とプリエンプション
● ここまでのプログラムだと、実行可能なスレッ
ドが複数ある場合はシステム・コールによって
順番に実行するようになっている
● しかし、組込みシステムではあるスレッドがレ
ディー状態になったとき、別のスレッドをさし
おいてでも動作させたい場合がある
– たとえば車のエアバック制御は、衝突を検知したら
一番に処理したい部分
● ある割込みが発生した場合に、必ず一定時間内
で処理を開始するという時間保証が行えるかど
うかを、OSのリアルタイム性と言う
- 9. リアルタイムOS
● リアルタイム性を提供するOSをリアルタイムOS
と呼ぶ
● ハードウェア制御だと、ある割込み発生から特
定の処理を一定時間内に必ず行う必要があるな
どの時間制約がある場合がある。こういったと
きにOSのリアルタイム性は重要
● 複数のスレッドがレディー状態のとき、どれを
動作するのか選択する必要があり、それに優先
度が利用される
- 10. プリエンプション
● スレッドの動作が別のスレッドに強制的に切り
替わる動作を一般的にプリエンプションと呼ぶ
– 優先度を持ったスレッドなら、優先度の低いスレッ
ドの実行が中断され、優先度の高いスレッドが実行
されることでこのように動作する
● プリエンプションが可能であることをプリエン
プティブと言い(先取り可能とも言う)、スレッ
ドが突然中断するようなことが無いのであれば
ノンプリエンプティブと呼ぶ
● KOZOSはプリエンプティブなOSとして開発して
いく
- 11. アイドル・スレッド
● スレッドに優先度がつくと、やることがないと
きにCPUを省電力モードにするアイドル・ス
レッドが簡単に実装できる
● 今のプログラムだとレディー・キューが空にな
るとシステムダウンしてしまうため、空になら
ないよう一番低い優先度で「ムダななんらかの
処理」をするスレッドを常に動かしておく必要
がある
while(1) {
// なにもしない状態
}
- 12. 省電力モード
● 一般的なCPUには省電力モードという状態があ
る
– x86でいうところのHLT命令かな
● CPUを省電力モードにすると命令の実行を停止
し、割込みが入るまで待つ状態になる
– クロックが止まるので省電になるようだ
● 他に動作する処理がないなら、アイドル・ス
レッドを実行して待機状態にすれば良い
while(1) {
// ビジーループよりこうした命令を使うべきだね
(CPUを省電力モードに遷移する命令);
}
- 14. プログラムの修正と追加
● 追加ファイル
– test09_1.c,test09_2,test09_3...スレッドとなる
サンプルプログラム
● 修正ファイル
– kozos.h,kozos.c...優先度を実装
– syscall.h,syscall.c...スレッド制御のシステム
コール追加
– main.c...アイドル・スレッド追加
– Makefile
- 15. プログラムの修正内容
● スレッドの状態を制御するシステム・コールの
追加
– kz_wait(),kz_sleep(),kz_wakeup(),kz_getid(),kz
_chpri()
● 優先度の追加
– 構造体に値を持たせて
● readayqueを配列化
– 優先度のスレッド別にまとめる形
– ここのらへんのスケジューリングのアルゴリズムが
少し複雑かなってぐらいで、あとは8thステップの
延長
- 17. ビルドの失敗(kozos.c)
● パディングのサイズを変更
typedef struct _kz_thread {
.
.
kz_context context;
char dummy[8]; ←dummy[16]からdummy[8]にした
} kz_thread;
- 18. プログラムの実行
/Users/sandai/12step/src/09/os% sudo cu -l /dev/tty.usbserial-FTG6PQ4H
kzload> run
.
.
test09_3 started.
test09_3 wakeup in (test09_1).
test09_1 sleep out.
test09_1 chpri in.
test09_3 wakeup out.
test09_3 wakeup in (test09_2).
test09_2 sleep out.
test09_2 chpri in.
test09_1 chpri out.
test09_1 wait in.
test09_3 wakeup out.
test09_3 wait in.
test09_2 chpri out.
test09_2 wait in.
test09_1 wait out.
test09_1 trap in.
test09_1 DOWN.
test09_1 EXIT.
test09_3 wait out.
test09_3 exit in.
test09_3 EXIT.
test09_2 wait out.
test09_2 exit.
test09_2 EXIT.
- 20. まとめ1
● 8thステップを理解していないと9thステップは
何をやっているのかわからないはず
● プログラムの修正部分に難しいコードはない
● システム・コールとスケジューリング部分のア
ルゴリズムの処理の流れが難しいので、そこを
まとめておこう
- 21. まとめ2
● 下記のkz_run()のうち、test09_1_id = ...の
処理の流れを記述しておく
● kz_start()でstart_threads()が起動した後の
ことなので注意
static int start_threads(int argc, char *argv[])
{
test09_1_id = kz_run(test09_1_main, "test09_1", 1, 0x100, 0,
.
.
- 22. まとめ3
● kz_run()
– kz_syscall()に渡すデータを構造体に保存
– kz_syscall()呼び出し
● kz_syscall()
– current->syscall.xxxにシステムコールのタイプと
kz_run()で受け取った構造体を設定
– asm volatile(“trapa #0”)で割込みが発生して
thread_intr()呼び出し
- 23. まとめ4
● thread_intr()
– handlers[type]()によりsyscall_intr()呼び出し
● 最終的にthread_run()が呼び出されてp-
>un.run.ret = にcurrentが代入される
– schedule()呼び出し
● この部分でスケジューリングされるため、優先
順位の高い初期スレッドのidleスレッドが動作
対象。test09_1_mainには映らないので注意
– dispatch()呼び出し
● currentにあるidleスレッドのstart_threadsが
実行を再開
- 24. まとめ5
● dispatch()が呼ばれると、割込みが発生した
kz_syscall()にあるasm volatile(“trapa
#0”)から続く
● 特に処理がないので、kz_run()に戻り、return
param.un.run.retでtest09_1_idにその値が代
入され、test09_2_id = ...と処理が同じよう
に続く
- 25. まとめまとめ
● kz_run()の流れは以上のような形
● 優先順位によってschedlue()で動作するスレッ
ドが決まるので、ここを気をつけてみる必要が
ある
● あとはkz_sleep()が難しいかも。レディー・
キューから外した場合、test09_1_idにスレッ
ドIDが保存されていて、kz_sleep()ではそれを
使ってレディー・キューに再度入れていること
になっている
– スリープさせたスレッドの管理が微妙な気がするけ
れど、こういうものなんだろうか