システムコールを作ろう! for FreeBSD/NetBSD

概要
  1. 新システムコールをカーネルに組み込む
    • 新システムコール定義の準備
    • 新システムコールのファイル作成
    • 新システムコールの定義
    • カーネル再構築
  2. libcから呼べるようにする
    • libcの再インストールは、シングルユーザモードで
新システムコールの定義の準備
  • /usr/src/sys/kern/syscalls.master
    システムコールの定義ファイル
    • システムコール番号
    • システムコールのタイプ
    • 関数のプロトタイプ
  • /usr/src/sys/kern/makesyscalls.sh
    システムコールを作るときに必要な作業をほとんどやってくれるシェルスクリプト

  1. syscalls.masterに自分のシステムコールを一行追加
    394 STD BSD { int syshello(void); }

  2. sh makesyscalls.sh syscalls.master
    各種ファイルをアップデート
    (FreeBSD)syscall.h, syscall-hide.h, sysproto.h
    (NetBSD)syscalls.c, init_sysent.c, syscall.h, syscallargs.h

新システムコールのファイル作成
  • 新しいファイルを作り、関数の中身を記述
    • /usr/src/sys/kern/syshello.c

      (FreeBSD)
      • /usr/src/sys/sys/sysproto.hに書かれている引数をそのまま使う
        (例)
        sysproto.h:
        int syshello __P((struct proc *, struct syshello_args *));

        syshello.c:
        int
        syshello(struct proc *a, struct syshello_args *b)
        {
        printf("hello\n");
        return 0;
        }
      (NetBSD)
      • sys/syscallargs.hに記述された関数プロトタイプにあわせる
      • #include <sys/syscallargs.h>する
        そのためには、更に別のヘッダファイルをincludeすることが必要になる
新システムコールの定義
  • /usr/src/sys/conf/files
    新しいファイルを追加したことを記述
    (FreeBSD) kern/syshello.c standard
    (NetBSD) file kern/syshello.c
カーネルの再構築
  • (FreeBSD)
    # cd /usr/src/sys/i386/conf/
    # config GENERIC
    # cd ../../compile/GENERIC
    # make depend && make
    # make install

  • (NetBSD)
    # cd /usr/src/sys/arch/i386/conf/
    # config GENERIC
    # cd ../compile/GENERIC
    # make depend && make
    # make install
libcから呼べるようにする
この時点ではシステムコールをユーザランドから呼び出すことができないので。
  • (FreeBSD)
    ユーザランドのヘッダファイルをアップデート
    (syscall.h,syscall-hide.h,sysproto.hを/usr/include/sysにコピー)
    # cp /usr/src/sys/sys/syscall.h /usr/include/sys/.
    # cp /usr/src/sys/sys/syscall-hide.h /usr/include/sys/.
    # cp /usr/src/sys/sys/sysproto.h /usr/include/sys/.
    # cd /usr/src/lib/libc
    # make obj
    # make depend
    # make all
    # make install

  • (NetBSD)
    # cp /usr/src/sys/sys/syscall* /usr/include/sys/
    /usr/src/lib/libc/sys/Makefile.incを編集

    __sysctl.S\
    syshello.S\ (←挿入)
    __posix_chown.S __posix_fchown.S __posix_lchown.S __posix_rename.S

    # cd /usr/src/lib/libc
    # make (アセンブラが勝手に出来て組み込まれる)

    libcの確認&再インストール
    # nm obj/libc.a | grep 'T syshello'
    0000008 T syshello
    (何も出てこなかったら失敗)

    シングルユーザモードにして、/usr/src/lib/libcでmake install
実行(テスト)用Cファイル
#include <stdio.h>
#include <sys/cdefs.h>

__BEGIN_DECLS
int syshello __P((void));
__END_DECLS

int
main (int argc, char **argv)
{
syshello();
return 0;
}

再起動してXを落として(もしくはxterm -C)実行してください。