view paper/chapter/03-gears.tex @ 61:e1dbf6e648ad

...
author anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Wed, 03 Feb 2021 00:24:14 +0900
parents 1ce43db7c038
children e88c0e26d331
line wrap: on
line source

\chapter{GearsOS}

GearsOSとはContinuation Based Cを用いて実装しているOSプロジェクトである。\cite{gears}
CodeGearとDataGearを基本単位として実行する。
GearsOSはOSとして実行する側面と、 CbCのシンタックスを拡張した言語フレームワークとしての側面がある。

現在のGearsOSはUnixシステム上のアプリケーションとして実装されているものと、 xv6の置き換えとして実装されているもの\cite{weko_195888_1}がある。


\section{Context}
Contextとは従来のOSのプロセスに相当する概念である。
GearsOSでのデータの単位から見ると、 MetaDataGearに相当する。

ContextはGearsOSの計算で使用されるすべてのDataGearとCodeGearを持つ。
各CodeGear、DataGearはContextはそれぞれ配列形式でContextにデータを格納する場所が用意されている。
CodeGearは配列の中にStubCodeGearへの関数ポインタが格納されている。
DataGearはInterfaceを利用したgoto時の値の保存場所として配列を利用している。
これらの配列の添え字はenumの番号である。

ノーマルレベルとメタレベルの切り分けの為に、ノーマルレベルではenumの番号を利用している。
enumの番号から対応するデータを切り分けるのは、 メタレベルでContextにアクセスして行われる。


Contextは配列形式のデータ格納場所のほかに、 ヒープ構造を所持している。
計算で必要なDataGearは、 CbCの中でアロケーションした場合はContextにヒープに書き込まれる。
ヒープにはDataGearと、書き込んだDataGearのメタ情報が記載されているMetaDataGearで構成されている。

\section{union Data型}

ContextはすべてのDataGearの型定義を持っている。
メタレベルで見れば、 この型定義は\texttt{union Data}型にすべて書かれている。
union Data型は、 C言語の共用体を使って実装されている。
共用体とは、構成するメンバ変数で最大の型のメモリサイズと同じメモリサイズになる特徴がある。
構造体と違い、1度に一つの型しか使うことができない。
実際にどの型が書き込まれているかは、 DataGearに付随しているMetaDataGearにアクセスすれば良い。



\section{GearsOSのビルドシステム}
GearsOSではビルドツールにCMakeを利用している。
ビルドフローを図\ref{fig:gearsbuild1}に示す。
CMakeはautomakeなどのMakeファイルを作成するツールに相当するものである。
GearsOSでプログラミングする際は、ビルドしたいプロジェクトをCMakeLists.txtに記述する。
CMakeは自身がコンパイルをすることはなく、ビルドツールであるmakeやninja-buildに処理を移譲している。
CMakeはmakeやninja-buildが実行可能なMakefile、 build.ninjaの生成までを担当する。


GearsOSのビルドでは直接CbCコンパイラがソースコードをコンパイルすることはなく、 間にPerlスクリプトが2種類実行される。
Perlスクリプトはビルド対象のGearsOSで拡張されたCbCファイルを、純粋なCbCファイルに変換する。
ほかにGearsOSで動作する例題ごとに必要な初期化関数なども生成する。
Perlスクリプトで変換されたCbCファイルなどをもとにCbCコンパイラがコンパイルを行う。
ビルドの処理は自動化されており、 CMake経由でmakeやninjaコマンドを用いてビルドする。

\begin{figure}[h]
  \begin{center}
   \includegraphics[width=150mm]{drawio/geasflow1.pdf}
  \end{center}
  \caption{GearsOSのビルドフロー}
  \label{fig:gearsbuild1}
\end{figure}



\section{GearsOSのCbCから純粋なCbCへの変換}
GearsOSはCbCを拡張した言語となっている。
ただしこの拡張自体はCbCコンパイラであるgcc、 llvm/clangには搭載されていない。
その為GearsOSの拡張部分を、等価な純粋なCbCの記述に変換する必要がある。
現在のGearsOSでは、 CMakeによるコンパイル時にPerlで記述された\texttt{generate\_stub.pl}と\texttt{generate\_context.pl}の2種類のスクリプトで変換される。

\section{generate\_stub.pl}
generate\_stub.plは各CbCファイルごとに呼び出される。
入力としてCbCファイルを受け取りメタ計算を含んだ形に変換し、 純粋なCbCファイルとして書き出す。
図\ref{fig:generate_stub_pl_1}に処理の概要を示す

\begin{figure}[h]
  \begin{center}
   \includegraphics[width=160mm]{drawio/gears_os_build_flow.pdf}
  \end{center}
  \caption{generate\_sub.plを使ったトランスコンパイル}
  \label{fig:generate_stub_pl_1}
\end{figure}

\section{generate\_context.pl}


\begin{itemize}
  \item \texttt{generate\_stub.pl}
  \begin{itemize}
    \item 各CbCファイルごとに呼び出されるスクリプト
    \item 対応するメタ計算を導入したCbCファイル(拡張子はc)に変換する
  \end{itemize}
  \item \texttt{generate\_context.pl}
  \begin{itemize}
    \item 生成したCbCファイルを解析し、使われているCodeGearを確定する
    \item context.hを読み込み、使われているDataGearを確定する
    \item Context関係の初期化ルーチンやCodeGear、 DataGearの番号であるenumを生成する
    \begin{itemize}
      \item 図\ref{fig:generate_context_1}に処理の概要を示す
    \end{itemize}
  \end{itemize}
\end{itemize}

これらのPerlスクリプトはプログラマが自分で動かすことはない。
Perlスクリプトの実行手順はCMakeLists.txtに記述しており、 makeやninja-buildでのビルド時に呼び出される。(ソースコード \ref{src:cmake1})

\lstinputlisting[label=src:cmake1, caption=CMakeList.txt内でのPerlの実行部分]{src/cmakefile.1.txt}

\begin{figure}[h]
  \begin{center}
   \includegraphics[width=130mm]{drawio/old_generate_context.pdf}
  \end{center}
  \caption{generate\_context.plを使ったファイル生成}
  \label{fig:generate_context_1}
 \end{figure}



\section{CbC xv6}
CbC xv6はGearsOSのシステムを利用してxv6 OSの置き換えを目指しているプロジェクトである。\cite{cbcxv6repo}
xv6はv6 OS\cite{lions1996lions}をx86アーキテクチャ用にMITによって実装し直されたものである。
Raspberry Pi上での動作を目指しているため、 ARMアーキテクチャ用に改良されたバージョンを利用している。\cite{xv6rpi}

書き換えにおいてはビルドシステムはCMakeを利用し、 Perlクロスコンパイラを導入してたりとGearsOSのビルドシステムとほぼ同じシステムを利用している。
GearsOSを使った比較的巨大な実用的なアプリケーションであるため、 xv6の書き換えを進むに連れて様々な面で必要な機能や課題が生まれている。
これらは都度GearsOSの開発に還元されている。
\section{ARM用ビルドシステムの作製}
GearsOSをビルドする場合は、x86アーキテクチャのマシンからビルドするのが殆どである。
この場合ビルドしたバイナリはx86向けのバイナリとなる。
これはビルドをするホストマシンに導入されているCbCコンパイラがx86アーキテクチャ向けにビルドされたものである為である。

CbCコンパイラはGCCとllvm/clang上に構築した2種類が主力な処理系である。
LVM/clangの場合はLLVM側でターゲットアーキテクチャを選択することが可能である。
GCCの場合は最初からjターゲットアーキテクチャを指定してコンパイラをビルドする必要がある。

時にマシンスペックの問題などから、 別のアーキテクチャ向けのバイナリを生成したいケースがある。
教育用マイコンボードであるRaspberry Pi\cite{rpi}はARMアーキテクチャが搭載されている。
Raspberry Pi上でGearsOSのビルドをする場合、 ARM用にビルドされたCbCコンパイラが必要となる。
Raspberry Pi自体は非力なマシンであるため、 GearsOSのビルドはもとよりCbCコンパイラの構築をRaspberry Pi上でするのは困難である。
マシンスペックが高めのx86マシンからARM用のバイナリをビルドして、 Raspberry Piに転送し実行したい。
ホストマシンのアーキテクチャ以外のアーキテクチャ向けにコンパイルすることをクロスコンパイルと呼ぶ。


GearsOSはビルドツールにCMakeを利用しているので、 CMakeでクロスコンパイル可能に工夫をしなければならない。
ビルドに使用するコンパイラやリンカはCMakeが自動探索し、 決定した上でMakefileやbuild.ninjaファイルを生成する。
しかしCMakeは今ビルドしようとしている対象が、自分が動作しているアーキテクチャかそうでないか、クロスコンパイラとして使えるかなどはチェックしない。
つまりCMakeが自動でクロスコンパイル対応のGCCコンパイラを探すことはない。
その為そのままビルドするとx86用のバイナリが生成されてしまう。


CMakeを利用してクロスコンパイルする場合、CMakeの実行時に引数でクロスコンパイラを明示的に指定する必要がある。
この場合x86のマシンからARMのバイナリを出力する必要があり、 コンパイラやリンカーなどをARMのクロスコンパイル対応のものに指定する必要がある。
また、 xv6の場合はリンク時に特定のリンカスクリプトを使う必要がある。
これらのリンカスクリプトもCMake側に、 CMakeが提供しているリンカ用の特殊変数を使って自分で組み立てて渡す必要がある。
このようなCMakeの処理を手打ちで行うことは難しいので、 \texttt{pmake.pl}を作成した。
\texttt{pmake.pl}の処理の概要を図\ref{fig:pmake}に示す。
\texttt{pmake.pl}はPerlスクリプトで、 シェルコマンドを内部で実行しクロスコンパイル用のオプションを組み立てる。
\texttt{pmake.pl}を経由してCMakeを実行すると、 makeコマンドに対応するMakefile、 ninja-buildに対応するbuild.ninjaが生成される。
以降はcmakeではなくmakeなどのビルドツールがビルドを行う。

\begin{figure}[h]
  \begin{center}
   \includegraphics[width=160mm]{drawio/pmake.pdf}
  \end{center}
  \caption{pmake.plの処理フロー}
  \label{fig:pmake}
 \end{figure}




 \section{Interfaceの取り扱い方法の検討}

 GearsOSのInterfaceはモジュール化の仕組みと\texttt{goto}文での引数の一時保管場所としての機能を持っている。
InterfaceのImplementのヘッダーファイルを実装したことで、 GearsOS上でInterfaceを実装する際に新たな方法での実装を検討した。
ImplementのCodeGearは今まではInterfaceで定義したCodeGearと1対1対応していた。
ImplementのCodeGearからgotoする先は、 入力として与えられたCodeGearか、 Implement内で独自に定義したCodeGearにgotoするケースとなっていた。
後者の独自に定義したCodeGearにgotoするケースも、 実装のCbCファイルの中に記述されているCodeGearに遷移していた。

GearsOSを用いてxv6 OSを再実装した際に、 実装側のCodeGearを細かく別けて記述した。
細分化によって1つのCbCファイルあたりのCodeGearの記述量が増えてしまうという問題が発生した。
見通しをよくする為に、 Interfaceで定義したCodeGearと直接対応するCodeGearの実装と、 それらからgotoするCodeGearで実装ファイルを分離することを試みた。