• 検索結果がありません。

部内向けスキルアップ研修 「組込みOS自作入門」

N/A
N/A
Protected

Academic year: 2022

シェア "部内向けスキルアップ研修 「組込みOS自作入門」"

Copied!
50
0
0

読み込み中.... (全文を見る)

全文

(1)

部内向けスキルアップ研修

「組込みOS自作入門」

2013年12月

8thステップ担当:松元

(2)

本日の内容

• スレッドを実装します

– スレッドとは?

– OSとは?

• もくもく会

– スレッドで動作するコマンド応答プログラム

• 必要に応じてプログラムの説明

(3)

たとえばこんな動作をさせる

• 以下の機能を持つ

– 0.1秒ごとにLED点滅

– 1秒ごとに液晶パネルに時刻表示 – シリアルからのコマンドに応答

• 一定時間ごとにサービスを実行できるか チェックする(ビジー・ループ)

8.1.1 OSはなぜ必要なのか?

(4)

メイン・ループ

0.1秒経過?

1秒経過?

シリアル受信?

LEDを点滅

液晶パネルに時刻表示

入力コマンドを実行

ダンプ出力 を追加

8.1.1 OSはなぜ必要なのか?

(5)

問題点

• ダンプするデータが大きい場合、処理に 時間がかかる

• LED点滅、時計表示がとまってしまう

• 一定回数ごとにメイン・ループに戻る

8.1.1 OSはなぜ必要なのか?

(6)

ダンプ処理

ダンプ処理中?

一定回数?

データ分繰り返す

前回の状態を復旧して再開

データ出力

状態を保存 メイン・ループより呼び出し

メイン・ループへ メイン・ループへ

データがなくなるまで

(7)

dump関数

• 定期的にメイン・ループに戻る

• 戻る前に実行中の状態を保存

• 関数の先頭で、前回の中断状態からの 再開か調べる

• 再開の場合、保存された状態を復旧

8.1.1 OSはなぜ必要なのか?

(8)

まとめると・・・

• 時間のかかる処理

• 回数が特定できないループ処理 では、中断・再開処理が必要

処理が複雑化してバグが発生しやすい

8.1.1 OSはなぜ必要なのか?

(9)

やりたいこと

• 定期的な処理の切り替え

• 処理状態の中断・保存・再開

サービス単位に区切る(タスク)

処理を共通化 スレッド化

8.1.2 タスクとスレッド

(10)

スレッドとは

• タスクごとに独立して動作させる

→ 並行処理

• CPUの処理時間を非常に短い単位に分割 し、複数のスレッドに順番に割り当てる ことによって、複数の処理を同時に行っ ているようにみせる

8.1.2 タスクとスレッド

(11)

用語

• システム・コール

– OSに対するサービス要求

• スケジューリング

– 次に動作すべきスレッドを選択

• ディスパッチ

– 選択されたスレッドの処理再開

8.1.2 タスクとスレッド

(12)

ディスパッチ

• 中断時に処理状態を保存

– スタックはスレッドごとに持つ

• 再開時にスタック・ポインタを 再開する スレッドのスタックのものに切り替える

8.1.2 タスクとスレッド

(13)

用語

• コンテキスト/コンテキスト情報

– スレッドの処理中断時に保存が必要なCPUの 状態

– スタック・ポインタ、プログラム・カウンタ などの各種レジスタ値

• コンテキスト切替え/ コンテキスト・

チェンジ

– スレッドのディスパッチのために、そのス レッドのコンテキストを読み込むこと

8.1.2 タスクとスレッド

(14)

用語

• アプリケーション・プログラム

– OS上でタスクとして独立して動作するプログ ラム

• コア/カーネル

– OSの中核

– 基本プログラム

8.1.3 アプリケーション・プログラムとは何か?

(15)

OS/割込み/スレッド

• OSは割込みの延長で動作し、スレッドを 管理する

1. 割込みハンドラからスレッドのコンテキス ト保存

2. スケジューリング

3. スレッドのコンテキストを復旧(ディス パッチ)

8.1.4 スレッドの切替え契機

(16)

システム・コール

• OSは資源を管理するための機能を持つ

– OSは割込みの延長

– スレッドとは切り離されている

• スレッド側から明示的に割込みを発生

• システム・コール命令を実行

→ システム・コール割込みが発生

• システム・コール割込みハンドラで応答

8.1.5 システム・コール

(17)

もくもく会の前に

• kz_start()

スレッド生成用スレッドを開始

• レディー・キュー

8.2 OSの実装

(18)

レディー・キュー

• スレッドごとにタスク・コントロール・

ブロック(TCB)を生成

→ タスクの情報を格納

• 実行可能なスレッドのタスク・コント ロール・ブロックをつなぐ(レディー・

キュー)

head tail readyque

nextポインタ 各種パラメータ

TCB nextポインタ

各種パラメータ

TCB nextポインタ

各種パラメータ

TCB NULL

8.2 OSの実装

(19)

レディー・キュー

• 実行中のスレッド(カレント・スレッ ド)の実行に区切りがついたら、レ ディー・キューの末尾に追加

• ラウンドロビン・スケジューリング

head tail readyque

nextポインタ 各種パラメータ

TCB

nextポインタ 各種パラメータ

TCB

nextポインタ 各種パラメータ

TCB NULL カレント

スレッド

NULL

8.2 OSの実装

(20)

用語

• キュー/先入れ先出し/FIFO

– 最初に入ってきたものを最初に処理する構造

• キューイング/エンキュー

– キューへ挿入

• デキュー

– キューからの抜き出し

• スタック:後入れ先出し/LIFO

8.2 OSの実装

(21)

もくもく会

• スレッドで動作するコマンド応答プログ ラム

– 教科書p.290~のソースコードリストを参照 – ブート・ローダー

ld.scr、intr.S、startup.s を修正

– OS

kozos.h、kozos.c、syscall.h、syscall.c、

test08_1.c を追加

ld.scr、startup.s、defines.h、main.c、

Makefile を修正

8.2 OSの実装

(22)

プログラムの実行

• ブートローダー

– make → make image → make write

• OS

– make

• コンソールで確認

– load → kozosを転送 – run

– echo test – exit

8.3 プログラムの実行

(23)

コードを追ってみよう

• startup.sよりmain()が呼ばれる(P.325)

• kz_start(

start_threads

,

"start", 0x100, 0, NULL

);

(P.317)

割込みハンドラの登録

setintr(SOFTVEC_TYPE_SYSCALL, syscall_intr);

setintr(SOFTVEC_TYPE_SOFTERR, softerr_intr);

current = (kz_thread *)thread_run(func, name,

stacksize, argc, argv);

dispatch(&current->context);

(24)

割込みハンドラの登録 (P.313)

• setintr(

SOFTVEC_TYPE_SYSCALL, syscall_intr

);

• setintr(

SOFTVEC_TYPE_SOFTERR, softerr_intr

);

– 割込みベクタの登録

softvec_setintr(type, thread_intr);(P.263)

SOFTVECS[type] = handler;

– 割込みハンドラの登録

handlers[type] = handler;

(25)

コードを追ってみよう

• startup.sよりmain()が呼ばれる(P.325)

• kz_start(start_threads,

"start", 0x100, 0, NULL

);

(P.317)

割込みハンドラの登録

setintr(SOFTVEC_TYPE_SYSCALL, syscall_intr);

setintr(SOFTVEC_TYPE_SOFTERR, softerr_intr);

current = (kz_thread *)thread_run(func, name,

stacksize, argc, argv);

dispatch(&current->context);

(26)

thread_run() (P.306)

• タスク・コントロール・ブロックを設定

– thp->init.func = func;

• スタックを設定

– スレッドの戻り先:thread_end() – スレッドの開始位置:thread_init() – 汎用レジスタ

– thread_init()に渡す引数(ER0):thp

• レディー・キューに接続

(27)

コードを追ってみよう

• startup.sよりmain()が呼ばれる(P.325)

• kz_start(start_threads,

"start", 0x100, 0, NULL

);

(P.317)

割込みハンドラの登録

setintr(SOFTVEC_TYPE_SYSCALL, syscall_intr);

setintr(SOFTVEC_TYPE_SOFTERR, softerr_intr);

current = (kz_thread *)thread_run(func, name,

stacksize, argc, argv);

dispatch(&current->context);

(28)

thread_run() (P.306)

• タスク・コントロール・ブロックを設定

– thp->init.func = func; ← start_threads

• スタックを設定

– スレッドの戻り先:thread_end() – スレッドの開始位置:thread_init() – 汎用レジスタ

– thread_init()に渡す引数(ER0):thp

• レディー・キューに接続

ER0:引数 ER1

ER6 開始位置

戻り先

(29)

コードを追ってみよう

• startup.sよりmain()が呼ばれる(P.325)

• kz_start(start_threads,

"start", 0x100, 0, NULL

);

(P.317)

割込みハンドラの登録

setintr(SOFTVEC_TYPE_SYSCALL, syscall_intr);

setintr(SOFTVEC_TYPE_SOFTERR, softerr_intr);

current = (kz_thread *)thread_run(func, name,

stacksize, argc, argv); → レディー・キューに登録

dispatch(&current->context);

→ スレッドを実行

(30)

スレッドを実行

• dispatch() (P.296)

– 引数:スレッドのスタック・ポインタ(ER0) – 汎用レジスタの値を復旧(ER0~ER6)

– rte→プログラム・カウンタとCCRの値を復旧

(31)

もう一度 thread_run() (P.306)

• タスク・コントロール・ブロックを設定

– thp->init.func = func; ← start_threads

• スタックを設定

– スレッドの戻り先:thread_end() – スレッドの開始位置:thread_init() – 汎用レジスタ

– thread_init()に渡す引数(ER0):thp

• レディー・キューに接続

ER0:引数 ER1

ER6 開始位置

戻り先

(32)

スレッドを実行

• thread_init() (P.306)

– thp->init.func(thp->init.argc,thp->init.argv);

→ start_threads – thread_end();

• start_threads() (P.325)

– kz_run(test08_1_main, “command”, 0x100, 0, NULL);

(33)

kz_run() (P.322)

• パラメータを設定

– param.un.run.func = func;

↑test08_1_main

• kz_syscall(KZ_SYSCALL_TYPE_RUN,

&param); (P.318)

– current->syscall.type = type;

– current->syscall.param = param;

– asm volatile(“trapa #0”);

→ トラップ割込みを発行

(34)

スレッドを実行

• thread_init() (P.306)

– thp->init.func(thp->init.argc,thp->init.argv);

→ start_threads – thread_end();

• start_threads() (P.325)

– kz_run(test08_1_main, “command”, 0x100, 0, NULL);

(35)

thread_end() (P.305)

• kz_exit() (P.323)

• kz_syscall(KZ_SYSCALL_TYPE_EXIT,

NULL); (P.318)

– current->syscall.type = type;

– current->syscall.param = param;

– asm volatile(“trapa #0”);

→ トラップ割込みを発行

(36)

トラップ命令による割込み

• 割込みベクタ

(37)

もう一度 割込みハンドラの登録

• setintr(

SOFTVEC_TYPE_SYSCALL, syscall_intr

);

• setintr(

SOFTVEC_TYPE_SOFTERR, softerr_intr

);

– 割込みベクタの登録

softvec_setintr(type, thread_intr);

SOFTVECS[type] = handler;

– 割込みハンドラの登録

handlers[type] = handler;

(38)

thread_intr() (P.316)

• handlers[type](); 割込みハンドラ実行

– SOFTVEC_TYPE_SYSCALL → syscall_intr – SOFTVEC_TYPE_SOFTERR → softerr_intr

• schedule();

• dispatch();

(39)

syscall_intr() (P.315)

• syscall_proc(current->syscall.type, current->syscall.param); (P.314)

– getcurrent();

– call_functions();

• call_functions(type, p); (P.314)

– KZ_SYSCALL_TYPE_RUNの場合

→ thread_run(p->un.run.func, ...);

– KZ_SYSCALL_TYPE_EXITの場合

→ thread_exit();

(40)

もう一度 thread_run() (P.306)

• タスク・コントロール・ブロックを設定

– thp->init.func = func; ← ???

• スタックを設定

– スレッドの戻り先:thread_end() – スレッドの開始位置:thread_init() – 汎用レジスタ

– thread_init()に渡す引数(ER0):thp

• レディー・キューに接続

ER0:引数 ER1

ER6 開始位置

戻り先

(41)

syscall_intr() (P.315)

• syscall_proc(current->syscall.type, current->syscall.param); (P.314)

– getcurrent();

– call_functions();

• call_functions(type, p); (P.314)

– KZ_SYSCALL_TYPE_RUNの場合

→ thread_run(p->un.run.func, ...);

– KZ_SYSCALL_TYPE_EXITの場合

→ thread_exit();

(42)

kz_run() (P.322)

• パラメータを設定

– param.un.run.func = func;

↑test08_1_main

• kz_syscall(KZ_SYSCALL_TYPE_RUN,

&param); (P.318)

– current->syscall.type = type;

– current->syscall.param = param;

– asm volatile(“trapa #0”);

→ トラップ割込みを発行

(43)

もう一度 thread_run() (P.306)

• タスク・コントロール・ブロックを設定

– thp->init.func = func; ← test08_1_main

• スタックを設定

– スレッドの戻り先:thread_end() – スレッドの開始位置:thread_init() – 汎用レジスタ

– thread_init()に渡す引数(ER0):thp

• レディー・キューに接続

ER0:引数 ER1

ER6 開始位置

戻り先

(44)

thread_intr() (P.316)

• handlers[type](); 割込みハンドラ実行

– SOFTVEC_TYPE_SYSCALL → syscall_intr – SOFTVEC_TYPE_SOFTERR → softerr_intr

• schedule(); → スケジューリング

• dispatch(); → スレッドを実行

(45)

スレッドを実行

• thread_init() (P.306)

– thp->init.func(thp->init.argc,thp->init.argv);

→ test08_1_main

• test08_1_main() (P.326)

– コンソールからのコマンドに応答する アプリケーション・プログラム

(46)

もうひとつのトラップ割込み

(47)

thread_end() (P.305)

• kz_exit() (P.323)

• kz_syscall(KZ_SYSCALL_TYPE_EXIT,

NULL); (P.318)

– current->syscall.type = type;

– current->syscall.param = param;

– asm volatile(“trapa #0”);

→ トラップ割込みを発行

(48)

syscall_intr() (P.315)

• syscall_proc(current->syscall.type, current->syscall.param); (P.314)

– call_functions();

• call_functions(type, p); (P.314)

– KZ_SYSCALL_TYPE_RUNの場合

→ thread_run(p->un.run.func, ...);

– KZ_SYSCALL_TYPE_EXITの場合

→ thread_exit(); (P.307) 終了メッセージを表示

タスク・コントロール・ブロックをクリア

(49)

まとめ

• OSの仕組み(スレッド)

• スレッドで動作するコマンド応答プログ ラムの作成

• OSの原型が完成!

(50)

次回の開催予定

• 9thステップ「優先度スケジューリング」

– 日時:1月15日(水)13:00~

– 場所:技術支援室 – 担当:谷口さん

参照

関連したドキュメント

[r]

1 Copyright© Japan Automobile Manufacturers Association,

Using the special C- mount ring adapter, the lens can be directly attached to a CCD camera, enabling it to be used as a low cost image ob- servation lens and variable focus lens

「自然・くらし部門」 「研究技術開発部門」 「教育・教養部門」の 3 部門に、37 機関から 54 作品

申込共通① 申込共通② 申込共通③ 申込共通④ 申込完了

Such a survey, if determined necessary, shall ensure that the attained EEDI is calculated and meets the requirement of regulation 21, with the reduction factor

都道府県(指定都市を含む)に設置義務が課されおり(法第 12 条、第 59 条の4、地 方自治法第 156 条別表5)、平成

波部忠重 監修 学研生物図鑑 貝Ⅱ(1981) 株式会社 学習研究社 内海富士夫 監修 学研生物図鑑 水生動物(1981) 株式会社 学習研究社. 岡田要 他