1. ホーム
  2. c

[解決済み] 構造体をxv6システムコールに渡す

2022-02-16 04:58:55

質問

xv6システムコールに直接パラメータを渡すことができず、ビルトインされたメソッドを使用することを余儀なくされていることは承知しています。

しかし、このサイトのすべての例と質問は、システムコールに整数を送信する方法についてです。その答えは、argint()メソッドを使用することです。

しかし、私の質問は、xv6システムコールに"struct"を渡す方法はあるのでしょうか?また、この目的のための統合されたメソッドはあるのでしょうか?

もしあるのなら、簡単な例を言っていただけませんか?

どのように解決するのですか?

システムコールで構造体を渡すことは可能です。

構造体そのものをシステムコール パラメータとして渡すことはできませんが、構造体へのポインタを渡すことは可能で、入力パラメータまたは出力パラメータとして使用することができます。

データへのポインタではなく、データそのものを引数として使用できるようにすると、システムコールの仕組みの要件が損なわれてしまいます。

既存のシステムコールfstatの実装を見てみましょう。

int fstat(int fd, struct stat *st);

fstatは、ファイル記述子番号を入力として要求し、それに対応するstats情報をstat構造体として出力します。

struct stat {
  short type;  // Type of file
  int dev;     // File system's disk device
  uint ino;    // Inode number
  short nlink; // Number of links to file
  uint size;   // Size of file in bytes
};

fstatは構造体ポインタを出力パラメータとして使用しますが、入力として使用する場合も同様です。

カーネルコード内の関数sys_fstatがfstatシステムコールの実装を開始します(XV6ではユーザ空間からのパラメータ取得をsys_*関数で処理するのが慣例となっています)。

int sys_fstat(void)
{
  struct file *f;
  struct stat *st;

  if(argfd(0, 0, &f) < 0 || argptr(1, (void*)&st, sizeof(*st)) < 0)
    return -1;
  return filestat(f, st);
}

この関数は、まず、fstat関数の第1引数で受け取ったファイル記述子番号に対応する構造体ファイルを取得します(argfdを使用)。次に、argptr を使用して、fstat 関数の 2 番目の引数で受け取った構造体 stat ポインタを取得し、与えられたポインタをローカル (関数スコープ) ポインタ変数に保存します。

この時点で、すべての引数がフェッチされ、カーネル実装で使用できるようになりました。

注意 struct stat ポインターはユーザー空間ポインター(仮想空間の下半分に位置する)ですが、カーネルがプロセスのシステムコールに対応するとき、プロセス自身のページングテーブルを使用するので、カーネルがここでそれを使用することは安全です。