view slide/sigos.html @ 19:954d8aee41fb

slide fix
author e165723 <e165723@ie.u-ryukyu.ac.jp>
date Tue, 28 May 2019 15:44:03 +0900
parents cef6ee71df2d
children 20d4a97ff72f
line wrap: on
line source






<!DOCTYPE html>
<html>
<head>
   <meta http-equiv="content-type" content="text/html;charset=utf-8">
   <title>継続を用いたxv6 kernelの書き換え</title>

   <meta name="generator" content="Slide Show (S9) v4.0.1 on Ruby 2.3.7 (2018-03-28) [universal.x86_64-darwin17]">
   <meta name="author"    content="Takahiro Sakamoto, Yu Tobaru, Shinji Kono" >

<!-- style sheet links -->
<link rel="stylesheet" href="s6/themes/projection.css"   media="screen,projection">
<link rel="stylesheet" href="s6/themes/screen.css"       media="screen">
<link rel="stylesheet" href="s6/themes/print.css"        media="print">
<link rel="stylesheet" href="s6/themes/blank.css"        media="screen,projection">

<!-- JS -->
<script src="s6/js/jquery-1.11.3.min.js"></script>
<script src="s6/js/jquery.slideshow.js"></script>
<script src="s6/js/jquery.slideshow.counter.js"></script>
<script src="s6/js/jquery.slideshow.controls.js"></script>
<script src="s6/js/jquery.slideshow.footer.js"></script>
<script src="s6/js/jquery.slideshow.autoplay.js"></script>

<!-- prettify -->
<link rel="stylesheet" href="scripts/prettify.css">
<script src="scripts/prettify.js"></script>

<script>
  $(document).ready( function() {
    Slideshow.init();

    $('code').each(function(_, el) {
      if (!el.classList.contains('noprettyprint')) {
        el.classList.add('prettyprint');
      }
    });
    prettyPrint();
  } );

</script>

<!-- Better Browser Banner for Microsoft Internet Explorer (IE) -->
<!--[if IE]>
<script src="s6/js/jquery.microsoft.js"></script>
<![endif]-->

    

</head>
<body>

<div class="layout">
  <div id="header"></div>
  <div id="footer">
    <div align="right">
      <img src="s6/images/logo.svg" width="200px">
    </div>
  </div>
</div>

<div class="presentation">

  <div class='slide cover'>
    <table width="90%" height="90%" border="0" align="center">
      <tr>
        <td>
          <div align="center">
              <h1><font color="#808db5">継続を用いたxv6 kernelの書き換え</font></h1>
          </div>
        </td>
      </tr>
      <tr>
        <td>
          <div align="left">
              Takahiro Sakamoto, Yu Tobaru, Shinji Kono
              琉球大学工学部情報工学科並列信頼研
            <hr style="color:#ffcc00;background-color:#ffcc00;text-align:left;border:none;width:100%;height:0.2em;">
          </div>
        </td>
      </tr>
    </table>
  </div>



<div class='slide'>
  
<!-- _S9SLIDE_ -->
<h2 id="研究目的">研究目的</h2>
<ul>
  <li>現代の OS では拡張性と信頼性を両立させることが要求されている</li>
  <li>信頼性をノーマルレベルの計算に対して保証し、拡張性をメタレベルの計算で実現することを目標に Gears OS を設計中である</li>
  <li>ノーマルレベルの計算とメタレベルの計算を切り離して記述するために Code Gear と Data Gear という単位を用いている</li>
  <li>Gears OS は Continuation based C(CbC) によってアプリケーションと OS そのものを記述する</li>
  <li>本研究では、CbC を用いた Gears OS の実装の前段階として xv6 での実装を目標とする</li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="メタ計算とは">メタ計算とは</h2>
<ul>
  <li>プログラムを記述する際、ノーマルレベルの処理の他に、メモリ管理やスレッド管理、CPU や GPU の資源管理等、記述しなければならない処理が存在する</li>
  <li>これらの計算をメタ計算と呼ぶ</li>
  <li>メタ計算はノーマルレベルの計算から切り離して記述したい</li>
  <li>そのためには処理を細かく分割する必要があるが、関数やクラスなどの単位は容易に分割できない</li>
  <li>そこで当研究室ではメタ計算を柔軟に記述するためのプログラミング言語の単位として Code Gear、Data Gear という単位を提案している</li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="continuatuin-based-c">Continuatuin based C</h2>
<ul>
  <li>Continuation based C (CbC) はこの Code Gear 処理の単位としてプログラミング言語として開発している。</li>
  <li>Code Gear は 関数呼び出し時の環境を使わずに次の Code Gear へと goto 文によって遷移する</li>
  <li>この goto 文による遷移を軽量継続と呼ぶ。</li>
  <li>継続を用いることによって状態遷移ベースでのプログラミングが可能である</li>
  <li>CbC は C と互換性のある言語なので、C の関数も呼び出すことができる</li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="cbc-のコード例">CbC のコード例</h2>
<ul>
  <li>CbC では Code Gear は <em>__code</em> Code Gear 名 (引数) の形で記述される</li>
  <li>Code Gear は戻り値を持たないので、関数とは異なり return 文は存在しない</li>
  <li>goto の後に Code Gear 名と引数を並べて、次の Code Gear の遷移を記述する</li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="cbc-のコード例-1">CbC のコード例</h2>
<ul>
  <li>この goto の行き先を継続と呼び、このときの a+b が次の Code Gear への出力となる</li>
</ul>

<pre><code>__code cg0(int a, int b){
  goto cg1(a+b);
}

__code cg1(int c){
  goto cg2(c);
}
</code></pre>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="cbc-の継続">CbC の継続</h2>
<ul>
  <li>Code Gear の継続を表す図である</li>
  <li>Code Gear 間の遷移は goto によって行われる
<!--* アセンブラレベルで見ると call ではなく jmp となっている--></li>
</ul>

<div style="text-align: center;">
 <img src="./images/cbc_goto.svg" alt="normalCodeGear" width="600" />
</div>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="gears-におけるメタ計算">Gears におけるメタ計算</h2>
<ul>
  <li>Gears OS ではメタ計算を Meta Code Gear、Meta Data Gear で表現する</li>
  <li>Meta Code Gear はノーマルレベルの Code Gear の直後に遷移され、メタ計算を実行する</li>
  <li>Meta Code Gear で OS の機能であるメモリ管理やスレッド管理を行う</li>
</ul>

<div style="text-align: center;">
 <img src="./images/meta_Code_Gear.svg" alt="normalCodeGear" width="600" />
</div>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="meta-gear">Meta Gear</h2>
<ul>
  <li>Gears OS では、Meta Code Gear は通常の Code Gear の直前、直後に挿入され、メタ計算を実行する</li>
  <li>通常の計算からはメタ計算は見ることができない</li>
</ul>
<div style="text-align: center;">
 <img src="./images/meta_gear2.svg" alt="MetaGear" width="600" />
</div>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="context">Context</h2>
<ul>
  <li>Gears OS では Context と呼ばれる、使用されるすべての Code Gear、Data Gear を持つ Meta Data Gear を持っている</li>
  <li>Gears OS は必要な Code Gear、Data Gear を参照したい場合、この Context を通す必要がある</li>
  <li>Context は Meta Data Gear であるため、Meta Code Gear を介してアクセスする</li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="interface">Interface</h2>
<ul>
  <li>Code Gear と Data Gear は Interface と呼ばれるまとまりとして記述される</li>
  <li>Interface は使用される Data Gear の定義と、それに対する Code Gear の集合である</li>
  <li>Interface の操作に対応する Code Gear の引数は Interface に定義されている Data Gear を通して行われる</li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="xv6-rpi-の-cbc-対応">xv6-rpi の CbC 対応</h2>
<ul>
  <li>オリジナルの xv6 は x86 アーキテクチャで実装されたものだが、xv6-rpi は Raspberry Pi 用に実装されたものである</li>
  <li>xv6-rpi を CbC で書き換えるために、GCC 上で実装した CbC コンパイラを ARM 向けに build し xv6-rpi をコンパイルした</li>
  <li>これにより、xv6-rpi を CbC で書き換える ことができるようになった</li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="xv6-の-cbc-への書き換え">xv6 の CbC への書き換え</h2>
<ul>
  <li>xv6 は UNIX V6 を x86 向けに再実装した OS である</li>
  <li>プロセスや仮想メモリ、カーネルとユーザーの分離、割り込み、ファイルシステムなどの基本的な Unix の構造を持つ</li>
  <li>CbC は Code Gear 間の遷移が goto による継続で行われるため、状態遷移ベースでのプログラミングに適している</li>
  <li>CbC で xv6 を書き換えることにより、状態遷移モデルによるモデル検査が可能となることを期待する</li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="xv6-の書き換えの方針">xv6 の書き換えの方針</h2>
<ul>
  <li>xv6 を CbC で書き換え、Gears OS の機能と置き換えることで Gears OS に OS の基本構造を持たせたい</li>
  <li>このためには xv6 をモジュール化することで、xv6 の機能を明らかにする必要がある</li>
  <li>xv6 の Interface を定義し、Gears OS の機能をこれに合わせることによって実現したい</li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="cbc-によるシステムコールの書き換え">CbC によるシステムコールの書き換え</h2>
<ul>
  <li>CbC は C と互換性のある言語であるため、元のソースコードから大きく崩すことなく必要な機能のみを CbC へと書き換えることが可能である</li>
  <li>ここでは実際にシステムコールを CbC で書き換えることによって、状態遷移ベースで書き換えるには何が必要か示すことにした</li>
  <li>今回は read システムコールの CbC 書き換えを行なった</li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="syscall関数">syscall関数</h2>
<ul>
  <li>syscall 関数 はシステムコールを呼び出す関数である
    <pre><code>void syscall(void)
{
  int num;
  int ret;
  num = proc-&gt;tf-&gt;r0;
  if((num &gt;= NELEM(syscalls)) &amp;&amp; (num &lt;= NELEM(cbccodes)) &amp;&amp; cbccodes[num]) {
      proc-&gt;cbc_arg.cbc_console_arg.num = num;
      goto (cbccodes[num])(cbc_ret);
  }
  if((num &gt; 0) &amp;&amp; (num &lt;= NELEM(syscalls)) &amp;&amp; syscalls[num]) {
      ret = syscalls[num]();
      if (num != SYS_exec) {
          proc-&gt;tf-&gt;r0 = ret;
      }
  } else {
      cprintf("%d %s: unknown sys call %d\n", proc-&gt;pid, proc-&gt;name, num);
      proc-&gt;tf-&gt;r0 = -1;
  }
}
</code></pre>
  </li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="sys_read-関数">sys_read 関数</h2>
<ul>
  <li>読み込むファイルの情報とアドレスを取り出し、fileread に渡している
    <pre><code>int sys_read(void)
{   
  struct file *f;
  int n;
  char *p;

  if(argfd(0, 0, &amp;f) &lt; 0 || argint(2, &amp;n) &lt; 0 || argptr(1, &amp;p, n) &lt; 0) {
      return -1;
  }

  return fileread(f, p, n);
}
</code></pre>
  </li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="cbc_read">cbc_read</h2>
<pre><code>__code cbc_read(__code (*next)(int ret)){
    struct file *f;
    int n;
    char *p;

    if(argfd(0, 0, &amp;f) &lt; 0 || argint(2, &amp;n) &lt; 0 || argptr(1, &amp;p, n) &lt; 0) {
        goto next(-1);
    }
    goto cbc_fileread(f, p, n, next);
}
</code></pre>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="fileread">fileread</h2>
<ul>
  <li>file の状態を確認し、対応した関数へ移行する
    <pre><code>int fileread (struct file *f, char *addr, int n)
{
  int r;

  if (f-&gt;readable == 0) {
      return -1;
  }

  if (f-&gt;type == FD_PIPE) {
      return piperead(f-&gt;pipe, addr, n);
  }

  if (f-&gt;type == FD_INODE) {
      ilock(f-&gt;ip);

      if ((r = readi(f-&gt;ip, addr, f-&gt;off, n)) &gt; 0) {
          f-&gt;off += r;
      }

      iunlock(f-&gt;ip);

      return r;
  }

  panic("fileread");
}
</code></pre>
  </li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="cbc_fileread">cbc_fileread</h2>
<pre><code>__code cbc_fileread1 (int r)
{   
    struct file *f = proc-&gt;cbc_arg.cbc_console_arg.f;
    __code (*next)(int ret) = cbc_ret;
    if (r &gt; 0)
        f-&gt;off += r;
    iunlock(f-&gt;ip);
    goto next(r);
}

__code cbc_fileread (struct file *f, char *addr, int n, __code (*next)(int ret))
{
    if (f-&gt;readable == 0) {
        goto next(-1);
    }

    if (f-&gt;type == FD_PIPE) {
        //goto cbc_piperead(f-&gt;pipe, addr, n, next);
        goto next(-1);
    }

    if (f-&gt;type == FD_INODE) {
        ilock(f-&gt;ip);
        proc-&gt;cbc_arg.cbc_console_arg.f = f;
        goto cbc_readi(f-&gt;ip, addr, f-&gt;off, n, cbc_fileread1);
    }

    goto cbc_panic("fileread");
}
</code></pre>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="readi">readi</h2>
<ul>
  <li>readi はファイルシステム上か特殊なデバイスを制御するかどうかで分岐する</li>
  <li>ここでは consoleread へ向かう処理を確認する
    <pre><code>int readi (struct inode *ip, char *dst, uint off, uint n)
{
  uint tot, m;
  struct buf *bp;

  if (ip-&gt;type == T_DEV) {
      if (ip-&gt;major &lt; 0 || ip-&gt;major &gt;= NDEV || !devsw[ip-&gt;major].read) {
          return -1;
      }

      return devsw[ip-&gt;major].read(ip, dst, n);
  }
...
</code></pre>
  </li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="cbc_readi">cbc_readi</h2>
<pre><code>__code cbc_readi (struct inode *ip, char *dst, uint off, uint n, __code (*next)(int ret))
{   
    uint tot, m;
    struct buf *bp;

    if (ip-&gt;type == T_DEV) {
        if (ip-&gt;major &lt; 0 || ip-&gt;major &gt;= NDEV || !cbc_devsw[ip-&gt;major].read) {
            goto next(-1);
        }

        goto cbc_devsw[ip-&gt;major].read(ip, dst, n, next);
    }
...
</code></pre>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="consoleread">consoleread</h2>
<ul>
  <li>console への入力を読み込み、待っている間スリープする
    <pre><code>int consoleread (struct inode *ip, char *dst, int n)
{
  uint target;
  int c;
  iunlock(ip);
  target = n;
  acquire(&amp;input.lock);

  while (n &gt; 0) {
      while (input.r == input.w) {
          if (proc-&gt;killed) {
              release(&amp;input.lock);
              ilock(ip);
              return -1;
          }
          sleep(&amp;input.r, &amp;input.lock);
      }
      c = input.buf[input.r++ % INPUT_BUF];
      if (c == C('D')) {  // EOF
          if (n &lt; target) {
              input.r--;
          }
          break;
      }
      *dst++ = c;
      --n;
      if (c == '\n') {
          break;
      }
  }
  release(&amp;input.lock);
  ilock(ip);
  return target - n;
}
</code></pre>
  </li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="cbc_consoleread">cbc_consoleread</h2>

<pre><code>__code cbc_consoleread (struct inode *ip, char *dst, int n, __code(*next)(int ret))
{   
    uint target;

    iunlock(ip);

    target = n;
    acquire(&amp;input.lock);

    if (n &gt; 0) {
        proc-&gt;cbc_arg.cbc_console_arg.n = n;
        proc-&gt;cbc_arg.cbc_console_arg.target = target;
        proc-&gt;cbc_arg.cbc_console_arg.dst = dst;
        proc-&gt;cbc_arg.cbc_console_arg.ip = ip;
        proc-&gt;cbc_arg.cbc_console_arg.next = next;
        goto cbc_consoleread2();
    }
    goto cbc_consoleread1();
}
</code></pre>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="cbc_consoleread-1">cbc_consoleread</h2>
<pre><code>__code cbc_consoleread2 ()
{   
    struct inode *ip = proc-&gt;cbc_arg.cbc_console_arg.ip;
    __code(*next)(int ret) = proc-&gt;cbc_arg.cbc_console_arg.next;
    if (input.r == input.w) {
        if (proc-&gt;killed) {
            release(&amp;input.lock);
            ilock(ip);
            goto next(-1);
        }
       goto cbc_sleep(&amp;input.r, &amp;input.lock, cbc_consoleread2);
    }
    goto cbc_consoleread1();
}

__code cbc_consoleread1 ()
{   
    int cont = 1;
    int n = proc-&gt;cbc_arg.cbc_console_arg.n;
    int target = proc-&gt;cbc_arg.cbc_console_arg.target;
    char* dst = proc-&gt;cbc_arg.cbc_console_arg.dst;
    struct inode *ip = proc-&gt;cbc_arg.cbc_console_arg.ip;
    __code(*next)(int ret) = proc-&gt;cbc_arg.cbc_console_arg.next;

    int c = input.buf[input.r++ % INPUT_BUF];

    if (c == C('D')) {  // EOF
        if (n &lt; target) {
            input.r--;
        }
        cont = 0;
    }

    *dst++ = c;
    --n;
    if (c == '\n') {
        cont = 0;
    }
    if (cont == 1) {
        if (n &gt; 0) {
            proc-&gt;cbc_arg.cbc_console_arg.n = n;
            proc-&gt;cbc_arg.cbc_console_arg.target = target;
            proc-&gt;cbc_arg.cbc_console_arg.dst = dst;
            proc-&gt;cbc_arg.cbc_console_arg.ip = ip;
            proc-&gt;cbc_arg.cbc_console_arg.next = next;
            goto cbc_sleep(&amp;input.r, &amp;input.lock, cbc_consoleread2);
        }
    }
    release(&amp;input.lock);
    ilock(ip);
    goto next(target - n);
}
</code></pre>


</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="sleep">sleep</h2>
<ul>
  <li>プロセスをスリープ状態にしてスケジューラーへ引き渡す
    <pre><code>void sleep(void *chan, struct spinlock *lk)
{
  if(proc == 0) {
      panic("sleep");
  }

  if(lk == 0) {
      panic("sleep without lk");
  }

  if(lk != &amp;ptable.lock){  //DOC: sleeplock0
      acquire(&amp;ptable.lock);  //DOC: sleeplock1
      release(lk);
  }

  proc-&gt;chan = chan;
  proc-&gt;state = SLEEPING;
  sched();

  proc-&gt;chan = 0;

  if(lk != &amp;ptable.lock){  //DOC: sleeplock2
      release(&amp;ptable.lock);
      acquire(lk);
  }
}
</code></pre>
  </li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="cbc_sleep">cbc_sleep</h2>
<pre><code>__code cbc_sleep1()
{   
    struct spinlock *lk = proc-&gt;lk;
    proc-&gt;chan = 0;

    if(lk != &amp;ptable.lock){  //DOC: sleeplock2
        release(&amp;ptable.lock);
        acquire(lk);
    }
    goto proc-&gt;cbc_next();
}

__code cbc_sleep(void *chan, struct spinlock *lk, __code(*next1)())
{   
    if(proc == 0) {
        panic("sleep");
    }

    if(lk == 0) {
        panic("sleep without lk");
    }

    if(lk != &amp;ptable.lock){  //DOC: sleeplock0
        acquire(&amp;ptable.lock);  //DOC: sleeplock1
        release(lk);
    }
    proc-&gt;chan = chan;
    proc-&gt;state = SLEEPING;
    proc-&gt;lk = lk;
    proc-&gt;cbc_next = next1;

    goto cbc_sched(cbc_sleep1);
}
</code></pre>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="sched">sched</h2>
<ul>
  <li>レジスタの値を切り替えて、スケジューラーへと戻る</li>
  <li>再開時は swtch の下から再開する
    <pre><code>void sched(void)
{   
  int intena;

  if(!holding(&amp;ptable.lock)) {
      panic("sched ptable.lock");
  }

  if(cpu-&gt;ncli != 1) {
      panic("sched locks");
  }

  if(proc-&gt;state == RUNNING) {
      panic("sched running");
  }

  if(int_enabled ()) {
      panic("sched interruptible");
  }

  intena = cpu-&gt;intena;
  swtch(&amp;proc-&gt;context, cpu-&gt;scheduler);
  cpu-&gt;intena = intena;
}
</code></pre>
  </li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="cbc_sched">cbc_sched</h2>
<pre><code>__code cbc_sched(__code(*next)())
{   
    int intena;

    if(!holding(&amp;ptable.lock)) {
        panic("sched ptable.lock");
    }

    if(cpu-&gt;ncli != 1) {
        panic("sched locks");
    }

    if(proc-&gt;state == RUNNING) {
        panic("sched running");
    }

    if(int_enabled ()) {
        panic("sched interruptible");
    }

    intena = cpu-&gt;intena;
    swtch(&amp;proc-&gt;context, cpu-&gt;scheduler);
    cpu-&gt;intena = intena;

    goto next();
}
</code></pre>
<!-- コメントアウトのやり方-->


</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="まとめと今後の方針">まとめと今後の方針</h2>
<ul>
  <li>現在は xv6 のシステムコールの一部のみの書き換えと、設計のみしか行っていないのでカーネル全ての書き換えをおこなう</li>
  <li>Gears OS にはメタ計算を実装する context は par goto の機能がある</li>
  <li>これらの機能を xv6 に組み込む方法について考察する必要がある</li>
  <li>xv6-rpi は QEMU のみの動作でしか確認してないため、実機上での動作が可能なように実装する必要がある</li>
</ul>

</div>


</div><!-- presentation -->
</body>
</html>