令和アドベントカレンダー: 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と呼べるものになると思いますので,いつかその実装をしていこうと思います。