diff paper/anatofuz-sigos.md @ 48:567288b8a89e

fix
author anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Thu, 07 May 2020 19:04:11 +0900
parents 49940c327b4e
children 72805ecaa331
line wrap: on
line diff
--- a/paper/anatofuz-sigos.md	Thu May 07 16:33:47 2020 +0900
+++ b/paper/anatofuz-sigos.md	Thu May 07 19:04:11 2020 +0900
@@ -5,11 +5,9 @@
 テスト以外の方法でOSの信頼性を高めたい。
 
 そこで数学的な背景に基づく形式手法を用いてOSの信頼性を向上させることを検討する。
-OSを構成する要素をモデル検査してデッドロックなどを検知する方法や、Agda定理証明支援系\cite{}を利用した証明ベースでの信頼性の確保などの手法が考えられる。
-形式手法で信頼性を確保するには、 まずOSの処理を証明などがしやすい形に変換して実装し直す必要がある。
-% これに適した形として、 状態遷移モデルが挙げられる。
+OSを構成する要素をモデル検査してデッドロックなどを検知する方法や、定理証明支援系Agda\cite{agda}を利用した証明ベースでの信頼性の確保などの手法が考えられる。\cite{Yang:2010:SLI:1806596.1806610}\cite{Klein:2009:SFV:1629575.1629596}\cite{Sigurbjarnarson:2016:PVF:3026877.3026879}
+形式手法で信頼性を確保するには、 まずOSの処理を証明などがしやすい形に変換して実装し直す必要がある。\cite{hyperKernel}
 OSの内部処理の状態を明確にし、 状態遷移モデルに落とし込むことでモデル検査などを通して信頼性を向上させたい。
-% 既存のOSはそのままに処理を状態遷移モデルに落とし込む為には、 まず既存のOSの処理中の状態遷移を分析し、仕様記述言語などによる再実装が必要となる。
 しかし仕様記述言語や定理証明支援系では、 実際に動くOSと検証用の実装が別の物となってしまうために、 C言語などでの実装の段階で発生するバグを取り除くことができない。
 実装のソースコードと検証用のソースコードは近いセマンティクスでプログラミングする必要がある。
 
@@ -19,18 +17,16 @@
 実装のソースコードはノーマルレベルであり検証用のソースコードはメタ計算だと考えると、OSそのものが
 検証を行ない、システム全体の信頼を高める機能を持つべきだと考える。
 ノーマルレベル上でのバグを例えばモデル検査のようなメタ計算によって発見し信頼性を向上させたい。
-% プログラマからはノーマルレベルの計算のみ実装するが、整合性の確認や拡張を行う際にノーマルレベルと同様の記述力でメタ計算も実装できる必要がある。
 
 ノーマルレベルの計算とメタ計算の両方の実装に適した言語としてContinuation Based C(CbC)がある。
-CbCは基本 goto で CodeGaar というコードの単位を遷移する言語である。通常の関数呼び出しと異なり、スタックあるいは環境と
-呼ばれる隠れた状態を持たない。このため、計算のための情報は CodeGearの入力にすべてそろっている。そのうちのいくつかはメタ計算、
+CbCは基本`goto`で`CodeGaar`というコードの単位を遷移する言語である。通常の関数呼び出しと異なり、スタックあるいは環境と
+呼ばれる隠れた状態を持たない。このため、計算のための情報は`CodeGear`の入力にすべてそろっている。そのうちのいくつかはメタ計算、
 つまり、OSが管理する資源であり、その他はアプリケーションを実行するためのデータ(DataGear)である。メタ計算とノーマルレベルの
 区別は入力のどこを扱うかの差に帰着される。
 CbCはCと互換性のあるCの下位言語であり、 状態遷移をベースとした記述に適したプログラミング言語である。
 Cとの互換性のために、 CbCのプログラムをコンパイルすることで動作可能なバイナリに変換が可能である。
-CbCは GCC \cite{}あるいは LLVM \cite{}上で実装されていて、通常のCのアプリケーションやシステムプログラ厶をそのまま包含できる。
-またCbCの基本文法は簡潔であるため、 Agdaなどの定理証明支援系\cite{}との相互変換や、 CbC自体でのモデル検査が可能であると考えられる。
-% すなわちCbCを用いて状態遷移を基本とした単位でプログラミングをすると、 形式手法で証明が可能かつ実際に動作するコードを記述できる。
+CbCは`GCC`\cite{gcc}\cite{weko_82695_1}あるいは`LLVM`\cite{llvm}\cite{llvmcbc}上で実装されていて、通常のCのアプリケーションやシステムプログラ厶をそのまま包含できる。
+またCbCの基本文法は簡潔であるため、 Agdaなどの定理証明支援系\cite{agda-ryokka}との相互変換や、 CbC自体でのモデル検査が可能であると考えられる。
 
 現在小さなunixであるxv6 kernelをCbCを用いて再実装している。
 再実装の為には、 既存のxv6 kernelの処理の状態遷移を分析し、継続を用いたプログラムに変換していく必要がある。
@@ -56,30 +52,24 @@
 
 ![lab:fig:cgdg, cap:CodeGearと入出力の関係図](fig/cgdg.pdf)
 
-CbCで階乗を求める例題をCode \ref{src:cbc_example}に示す。
-例題ではCodeGearとして`factorial`を宣言している。
-`factorial`はCodeGearの引数として`struct F`型の変数`arg`を受け取り、`arg`のメンバー変数によって`factorial`の再帰呼び出しを行う。
-CodeGearの呼び出しは`goto`文によって行われる。
-この例題を状態遷移図にしたものを図\ref{fig:factorial_cbc}に示す。
-図中の四角がDataGear、 円がCodeGearに対応する。
-
+CbCを利用したシステムコールのディスパッチ部分をCode \ref{src:cbc_example}に示す。
+この例題では特定のシステムコールの場合、 CbCで実装された処理に`goto`文をつかって継続する。
+例題ではCodeGearへのアドレスが配列`cbccodes`に格納されている。
+引数として渡している`cbc_ret`は、 システムコールの返り値の数値をレジスタに代入するCodeGearである。
 
-``` lab:src:cbc_example, cap:CbCで階乗を求める例題
-__code factorial(struct F arg) {
-    if (arg.n<0) {
-        exit(1);
+``` lab:src:cbc_example, cap:CbCを利用したシステムコールのディスパッチ
+void syscall(void)
+{
+    int num;
+    int ret;
+
+    if((num >= NELEM(syscalls)) && (num <= NELEM(cbccodes)) && cbccodes[num]) {
+        proc->cbc_arg.cbc_console_arg.num = num;
+        goto (cbccodes[num])(cbc_ret);
     }
-    if (arg.n==0) {
-      goto arg.next(arg);
-    } else {
-      arg.r *= arg.n;
-      arg.n--;
-      goto factorial(arg);
-    }
-}
 ```
 
-![lab:fig:factorial_cbc, cap:CbCで階乗を求める例題の状態遷移](fig/factorial_cbc.pdf)
+![lab:fig:factorial_cbc, cap:CbCを利用したシステムコールディスパッチの状態遷移](fig/cbc_syscall_Trap)
 
 CodeGearは関数呼び出し時のスタックを持たない為、一度あるCodeGearに遷移してしまうと元の処理に戻ってくることができない。
 しかしCodeGearを呼び出す直前のスタックは保存されるため、 部分的にCbCを適用する場合はCodeGearを呼び出す`void`型などの関数を経由することで呼び出しが可能となる。
@@ -94,7 +84,7 @@
 その為には証明に使用される定理証明支援系や、 モデル検査機での表現に適した状態遷移単位での記述が求められる。
 CbCで使用するCodeGearは、 状態遷移モデルにおける状態そのものとして捉えることが可能である。
 CodeGearを元にプログラミングをするにつれて、 CodeGearの入出力のDataも重要であることが解ってきた。
-CodeGearとその入出力であるDataGearを基本としたOSとして、 GearsOSの設計を行っている。
+CodeGearとその入出力であるDataGearを基本としたOSとして、 GearsOSの設計を行っている。\cite{gears}
 現在のGearsOSは並列フレームワークとして実装されており、 実用的なOSのプロトタイプ実装として既存のOS上への実装を目指している。
 
 GearsOSでは、 CodeGearとDataGearを元にプログラミングを行う。
@@ -123,9 +113,9 @@
 
 # xv6 kernel
 
-xv6とはマサチューセッツ工科大学でv6 OSを元に開発された教育用のUNIX OSである。
+xv6とはマサチューセッツ工科大学でv6 OS\cite{lions1996lions}を元に開発された教育用のUNIX OSである。\cite{xv6}
 xv6はANSI Cで実装されており、 x86アーキテクチャ上で動作する。
-Raspberry Pi上での動作を目的としたARMアーキテクチャのバージョンも存在する。
+Raspberry Pi\cite{rpi}上での動作を目的としたARMアーキテクチャのバージョンも存在する。\cite{xv6rpi}
 本論文では最終的にRaspberry Pi上での動作を目指しているために、 ARMアーキテクチャ上で動作するxv6を扱う。
 
 xv6は小規模なOSだがファイルシステム、 プロセス、システムコールなどのUNIXの基本的な機能を持つ。
@@ -137,14 +127,14 @@
 本論文ではxv6の継続の分析をシステムコール部分とファイルシステム、 仮想メモリなどのOSの根幹部分でそれぞれ行った。
 
 
-# xv6のシステムコールの継続の分析
+# xv6のシステムコールの継続の分析と書き換え
 xv6の処理を継続を中心とした記述で再実装を行う。
 この際に、 xv6のどの処理に着目するかによって継続の実装が異なっていくことが実装につれてわかった。
 
-まずxv6の`read` システムコールに着目し、 システムコール内部でどのような状態を遷移するかを分析した。
+まずxv6の`read` システムコールに着目し、 システムコール内部でどのような状態を遷移するかを分析した。 \cite{weko_195888_1}
 分析結果をCbCのCodeGearに変換し、 状態遷移図におこしたものを図\ref{fig:cbc_readsyscall}に示す。
 
-![lab:fig:cbc_readsyscall, cap:readシステムコールの状態遷移](fig/readsyscall_state.pdf)
+![lab:fig:cbc_readsyscall, cap:readシステムコールの状態遷移](fig/readsyscall.pdf)
 
 CbCで再実装した`read`システムコールは、 xv6の`read`システムコールのディスパッチ部分から、 `cbc_read`CodeGearに`goto`文で軽量継続される。
 継続後はreadする対象によって`cbc_readi`や、 `cbc_consoleread`などに状態が変化していく。
@@ -204,7 +194,7 @@
 
         if (dip->type == 0) {  // a free inode
             memset(dip, 0, sizeof(*dip));
-            // omission
+            ...
             return iget(dev, inum);
         }
         brelse(bp);
@@ -229,8 +219,9 @@
 ```
 
 Code\ref{src:allocinode_loopcheck}ではループ条件の成立を`if`文で確認し、ループ処理に移行する場合は `allocinode_loop`へ遷移する。
+`goto`文の中の引数の1つ`next(...)` は、 APIとして呼び出した`ialloc`の次の継続のCodeGearに対して、 `context`などの環境を渡す構文である。
 ループ条件が満たされなかった場合は、 コンテキストから`panic`に関するCodeGearの集合を取り出し、 集合中の`panic` CodeGearへと遷移する。
-オリジナルの処理では、 ループ中に`dip->type == 0`が満たされた場合は関数から`return`文により関数から復帰する。
+オリジナルの処理では、 ループ中に`dip->type == 0`が満たされた場合は関数から`return`文により関数から復帰する。
 CodeGearではCode\ref{src:alloc_loop}内で、 状態が分けられる。
 この先の継続は、 復帰用のCodeGearかループの先頭である`allocinode_loopcheck`に再帰的に遷移するかになる。
 
@@ -282,7 +273,7 @@
 
 void userinit(void)
 {
-// omission
+...
 
     if((p->pgdir = kpt_alloc()) == NULL) {
         panic("userinit: out of memory?");
@@ -292,7 +283,7 @@
 
     p->sz = PTE_SZ;
     memset(p->tf, 0, sizeof(*p->tf));
-// omission
+...
 }
 ```