最も簡単な解決策は、仮想ファイルに対する独自のファイル操作を使用して、カーネルドライバーにキャラクターデバイスを作成することだと思います。次に、ユーザー空間はこのデバイス O_RDWR
を開くことができます . 2 つの主要なファイル操作を実装する必要があります:
-
read
-- これは、カーネルがデータをユーザー空間に戻す方法です。この関数は、read()
を呼び出すユーザー空間スレッドのコンテキストで実行されます。 システムコール、そしてあなたの場合、カーネルが出力を知る必要がある別のシード値を持つまでブロックする必要があります. -
write
-- これは、ユーザー空間がデータをカーネルに渡す方法です。あなたの場合、カーネルは以前の読み取りに対する応答を取得して、それをハードウェアに渡します。
その後、ユーザー空間で単純なループが発生します:
while (1) {
read(fd, buf, sizeof buf);
calculate_output(buf, output);
write(fd, output, sizeof output);
}
カーネル内にループはまったくありません。すべては、物事を動かしているユーザー空間プロセスのコンテキストで実行され、カーネル ドライバーは、ハードウェアとの間でデータを移動するだけの役割を果たします。
カーネル側での「ここでランダムなことをする」が何であるかによっては、それほど単純に行うことができない場合があります。カーネル ループが本当に必要な場合は、カーネル スレッドを作成してそのループを実行し、input_data
の行に沿っていくつかの変数を用意する必要があります。 、 input_ready
、 output_data
と output_ready
、いくつかの待機キューと必要なロックと共に。
カーネルスレッドがデータを読み取るとき、データを input_ready
に入れます input_ready
を設定します 入力待ち行列にフラグを立てて信号を送ってから、 wait_event(<output_ready is set>)
を実行します . read
ファイル操作は wait_event(<input_ready is set>)
を実行します 準備ができたら、データをユーザー空間に返します。同様に write
ファイル操作は、ユーザー空間から取得したデータを output_data
に配置します output_ready
を設定します そして、出力待ち行列にシグナルを送ります。
別の (醜く、移植性に欠ける) 方法は、 ioperm
のようなものを使用することです 、 iopl
または /dev/port
低レベルのハードウェア アクセスを含め、ユーザー空間ですべてを完全に実行します。