---
title: みかん本輪読会_24
tags: 
author: [こた](https://www.docswell.com/user/kota)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/8JDX3XD67G.jpg?width=480
description: みかん本輪読会_24 by こた
published: August 17, 25
canonical: https://www.docswell.com/s/kota/574LPD-mikan-24
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/8JDX3XD67G.jpg)

みかん本輪読会
24章
複数のターミナル


# Page. 2

![Page Image](https://bcdn.docswell.com/page/VEPP4P6ZE8.jpg)

ターミナルを増やす
p.560
- 15章でターミナルを作った
- けど同時起動は出来なかった
→ 今回は複数のアプリを同時に起動させるのが目標
- アプリの起動方法はTerminal::ExecuteFile()の中で
ELFファイルをメインメモリに読み込んでいる


# Page. 3

![Page Image](https://bcdn.docswell.com/page/27V2X23M7Q.jpg)

F2を押してターミナルを生成する
p.560~561
- リスト24.1のようにF2キーを押すとターミナルクラスを
新規に生成するコードを追加してみる
- 図24.1のように2つ目のターミナルが開いた
リスト24.1
- でも2つ目のターミナル
のカーソルが点滅してない
- 他にも例外が発生する
→ 不具合に対処する


# Page. 4

![Page Image](https://bcdn.docswell.com/page/5JGRVR3X7L.jpg)

カーソル点滅を自分で
p.561
- 今のカーソル点滅の仕組みは、メインタスクが管理するタイ
マがタイムアウトした時に、そのタイムアウトメッセージを
ターミナルタスクにコピーして送信することで実現している
- この仕組みではターミナルが増えた時にどのターミナルへ
メッセージを送るかをメインタスクが判断する必要があり、
コードが複雑になる
- ターミナルが非アクティブでもカーソルが点滅する


# Page. 5

![Page Image](https://bcdn.docswell.com/page/47QV6V55EP.jpg)

カーソル点滅を自分で
p.561~563
- ターミナル自身がカーソル点滅を制御する
- ターミナルタスクが起動すると独自にタイマ計測
- ターミナルクラスがウィンドウのアクティブ/非アクティ
ブを検知できるようにし、状態をメッセージタスクに送
信することで非アクティブ時のカーソル点滅をなくす
(リスト24.2~24.5)


# Page. 6

![Page Image](https://bcdn.docswell.com/page/KE4M4M9V71.jpg)

複数アプリの同時起動
p.564~565
- 複数のアプリを同時起動すると例外が発生する
→ 仮想メモリ領域が競合するから (19.2 参照)
→ 対策のために階層ページング構造の切り替えを行う
- アプリは専用の階層ページング構造を持ち、アプリを切
り替える際はCPUが参照する階層ページング構造の切
り替えも行う (図24.4)


# Page. 7

![Page Image](https://bcdn.docswell.com/page/L71848K4JG.jpg)

複数アプリの同時起動
p.564~566
- 階層ページング構造の最上位データ構造はPML4
- CPUのCR3レジスタがPML4の物理アドレスを保持し
て仮想アドレスと変換する (19.3 参照)
→ アプリ毎にPML4を最上位とする階層ページング構造
を持たせて、アプリ切り替え時にCR3レジスタを書き換え
る


# Page. 8

![Page Image](https://bcdn.docswell.com/page/G7WZXZDZ72.jpg)

複数アプリの同時起動
p.566~567
- リスト24.6で実行可能ファイルをロードする前に
PML4を設定する
- リスト24.7で新しいPML4を構築して有効化する
→ PML4として用いるデータ構造を生成し、OS用のペー
ジマップ設定をコピーし、構築したPML4をCR3と現在の
タスクの設定する


# Page. 9

![Page Image](https://bcdn.docswell.com/page/4JZ161GLE3.jpg)

複数アプリの同時起動
p.567
- リスト24.7ではコピーするPML4の要素数が256個
- PML4の全体のサイズは64ビットx512なので半分
- PML4は前半がOS用、後半がアプリ用となっている
- OS用のメモリマッピングは全てのアプリで共通なのでそ
のままコピーできるPML4をCR3及び現在のタスクに設
定することでSetupPML4()の処理は完了
- 新しいPML4でアプリの実行ファイルをロードする


# Page. 10

![Page Image](https://bcdn.docswell.com/page/YE6L2LYM7V.jpg)

複数アプリの同時起動
p.568
- リスト24.8でアプリ終了時の処理を行う
- CleanPageMaps()でPML4より下の階層ページング
構造を削除
- 今までのPML4はOS用として作り、使いまわしていた
ので削除は不要だったが、アプリ用に生成したPML4
では削除する必要がある


# Page. 11

![Page Image](https://bcdn.docswell.com/page/GE5121GQJ4.jpg)

複数アプリの同時起動
p.568
- リスト24.9ではタスク構造体からPML4の登録を解除し、
CR3をリセットしてOS用のPML4を指す処理を作る
- タスク構造体から登録を解除する処理とCR3のリセット処理
の順番は大事
→ 逆になるとタスクが戻ってきた際にタスク構造体にはまだ有
効なPML4が設定されており、そのPML4がCR3に設定されてし
まうのでCR3をリセットする意味がなくなる
- リスト24.10ではCR3にPML4を設定する処理を実装


# Page. 12

![Page Image](https://bcdn.docswell.com/page/972141YWER.jpg)

ターミナルなしのアプリ起動
p.571
- 今まではターミナルを起動してアプリを起動してた
→ アプリを立ち上げるだけで大量のターミナルが…
- ただアプリの起動はターミナルに依存しているのでター
ミナルなしではなくターミナルを見えなくする方向で実装
する
- リスト24.13ではnotermコマンドを新たに作成


# Page. 13

![Page Image](https://bcdn.docswell.com/page/DJYZMZG9EM.jpg)

ターミナルなしのアプリ起動
p.571~574
- notermコマンドで起動したターミナルは図形描画(リ
スト24.15)、画面表示(リスト24.16)、カーソル表示(リ
スト24.17)、ウィンドウ表示(リスト24.18)がされずに
起動する


# Page. 14

![Page Image](https://bcdn.docswell.com/page/V7N3W3GD78.jpg)

OSを守ろう
p.575
- 今のMikanOSではアプリがCPU例外を発生させると
例外ハンドラが呼び出され、OSがフリーズする
- バグを完全に無くすことは難しいのでアプリが例外を
発生させてもOSがフリーズしない仕組みを作る


# Page. 15

![Page Image](https://bcdn.docswell.com/page/YJ99X9W8J3.jpg)

OSを守ろう
p.577
- 例外発生させたアプリを特定して強制終了させる
- 例外発生がOSかアプリかは割り込み発生時のCSレジ
スタの値で判別可能
- CSの下位3ビットはCPLフィールドでCPUの動作権限を
表し、OSは0アプリは3になる
→ CPLの値が3ならばアプリを終了させる


# Page. 16

![Page Image](https://bcdn.docswell.com/page/GJ8929NZED.jpg)

OSを守ろう
p.579
- リスト24.20はExitApp()によってアプリを強制終了さ
せている
- リスト24.21はExitApp()を利用したKillApp()とそれを
呼び出す例外ハンドラの実装
- CPL=3であればExitApp()でアプリを強制終了
- ExitApp()を呼ぶ前にsti命令でIF=1に設定する
→ 次の割り込みや例外が受け付けられるように


# Page. 17

![Page Image](https://bcdn.docswell.com/page/LJLW2WP17R.jpg)

アプリを起動してから強制終了まで
p.579
1. CallApp()によりアプリが起動、PSPにアプリ用スタッ
クが設定され、CSはアプリ用(CPL=3)になる
2. アプリがCPU例外を発生させる
3. CPUはIDTを調べ適切な割り込みハンドラを呼び
CPUはCSにOS用の値を、IFビットに0を設定する
4. 割り込みハンドラはKillApp()を呼び出す。CPL=3より
アプリ実行中の例外と判断される


# Page. 18

![Page Image](https://bcdn.docswell.com/page/47M98945JW.jpg)

アプリを起動してから強制終了まで
p.579
5. stiによりIF=1となり、次の割り込みが許可される
6. KillApp()はExitApp()を呼び出す。ExitApp()はRSP及
び各レジスタをOS用に復元し、CallApp()の次の行にジャ
ンプする


# Page. 19

![Page Image](https://bcdn.docswell.com/page/P7RG5GWZJ9.jpg)

OSを守ろう
p.579~580
- フラットバイナリ形式のアプリ実行機能を削除
→ CPL=0 つまりOSモードのまま実行するので今回実装
した保護機能が働かない
- ELF形式に対応しているので対応する必要がない


