panda's tech note

令和アドベントカレンダー: advos

Extra Day 4: システムコールの応用

今日はシステムコールをユーザランドプログラムから呼び出す例を書きます。本来はメモリ空間もユーザランドで実行したいところですが,今回は簡単のために,カーネルと共有のメモリ空間で動くtask_a()から呼び出すシステムコールを実装します。実装はsrc/kernel/arch/x86_64/asm.Sおよびsrc/kernel/arch/x86_64/arch.cにあります。

システムコールの呼び出し関数の実装

システムコールの呼び出し規則は,昨日実装したsyscall命令のエントリポイントの呼び出し規則に沿う必要があります。そのため,syscall()関数をアセンブリで実装しました。この関数は本来ユーザランドから呼び出すため,libcなどのライブラリに実装するものですが,今回は。src/kernel/arch/x86_64/asm.Sに実装しました。

この関数は第1引数にシステムコール番号,第2〜第7引数は呼び出されるシステムコールの第1〜第6引数に対応します。

/* int syscall(arg0, ..., arg5) */
_syscall:
    pushq	%rbp
    movq	%rdi,%rax
    movq	%rsi,%rdi
    movq	%rdx,%rsi
    movq	%rcx,%rdx
    movq	%r8,%r10
    movq	%r9,%r8
    movq	-8(%rsp),%r9
    syscall
    popq    %rbp
    ret

システムコールの実装

昨日は767番のシステムコールとして,hlt命令を実装しましたが,同様に,画面の23行目にカウンタを表示するシステムコールを以下の通り実装します。引数にカウンタを取るようにしました。

void
sys_print_counter(uint64_t cnt)
{
    uint16_t *base;

    base = (uint16_t *)0xc00b8000;
    base += 80 * 22;
    print_hex(base, cnt, 8);
}

これを766番のシステムコールとして登録します。

    syscall[766] = sys_print_counter;

システムコールの呼び出し

システムコールの呼び出しは,上記で定義したsyscall()関数を呼び出します。第1引数にシステムコール番号,第2引数にはsys_print_counter()の第1引数を指定します。

        syscall(766, cnt);

まとめ

このアドベントカレンダーでは,PXEブートとシステムコールを実装しました。ユーザランドプロセスの実装とfork(),プロセス間通信があればOSと呼べるものになると思いますので,いつかその実装をしていこうと思います。