システムコールがユーザー空間コールバック関数を受け入れないのはなぜですか?

システムコールがユーザー空間コールバック関数を受け入れないのはなぜですか?

この質問は拡張です。情報を返すためにシステムコールにバッファを渡す必要があるのはなぜですか?システムコールが内部的にバッファを割り当てられないのはなぜですか?メモリ割り当ては、コールバックをシステムコールに渡す多くの同期の1つであるためです。

元のシステムコールは、バッファに書き込む前に割り当てるバッファのサイズを知ることができるので、バッファが必要な元のシステム呼び出しのバリエーションに割り当てコールバックを渡したいと思います。

多くのファイルシステムAPI(posix / * nixだけでなくWindows / NTもこれを行います)では、常にパスバッファのaxバイトを渡す必要があります(xは256、1024、4096、またはMAX_PATHです)。バッファサイズを示すには関数にxを渡す必要があり、バッファが許可するよりも多くのスペースが必要な場合、関数は失敗する可能性があります。

システムコールがユーザー空間関数を呼び出すのを防ぐ制限はありますか?可能ですが、システムコールが呼び出しユーザースペースコンテキストとコールバックユーザースペースコンテキストを保持する必要があるため、複雑ですか?スレッド切り替えの観点から見ると、すべてのシステムコールはアトミックでなければなりません。

ベストアンサー1

システムコールはカーネルコードを実行します。カーネルはユーザーモードコードを信頼しないため、システムコールにコールバックが必要な場合、カーネルモードでそのコールバックを実行することはできません。ユーザーモードでコールバックを実行する必要があります。

システムコールは、コールバックが実行する操作を決定できません。コールバックは独自のシステムコールを実行できます。たとえば、メモリを割り当てるコールバックは、プロセスにより多くのメモリを提供するために、sbrkまたは同じシステムコールを呼び出す必要があります。mmapしたがって、ネストされたシステムコールの実行コンテキストに加えて、カーネルは保留中のシステムコールに対する追加の実行コンテキストを維持する必要があります。カーネルは、プロセスごとに複数の実行コンテキストを持つことができます。これがカーネルスレッドの目的です。ただし、一部のコンテキストは他のコンテキスト内にネストされているため、これらのコンテキストには追加の構造が必要です。

システムコールがすべての中間情報をプロセスに渡すことで、この追加の複雑さを回避できます。プロセスに必要なコールバックコードを実行させ、準備ができたら連続システムコールを呼び出します。このように、カーネルは単純な実行モデル(システムコール呼び出し、システムコール実行、システムコールリターン)を維持し、プロセスは必要に応じてコールバックを実行できます。

さて、ここにいます。これが今動作する方法です。プロセスは、必要なバッファーのサイズを照会するためにシステム呼び出しを行い、データを取得するために別のシステム呼び出し(おそらく異なるパラメーターを持つ同じシステム呼び出し番号)を作成できます。

コールバックの実行中にデータが変更される可能性があるという本質的な問題があります。システムコールはアトミックである必要はありませんが、特定の瞬間にシステムの一貫したビューを提供する必要があります。たとえば、プロセスがファイルからデータを読み取ろうとすると、コールバックの実行中にファイルが大きくなる可能性があります。カーネルは、コールバックが指定された時間内に完了するか実際に完了すると信頼できないため、コールバックの実行中にカーネルはファイルの更新を妨げることはできません。したがって、ユーザーエリアコードは、いかなる場合でもこれらの困難を処理する必要があります。ポストコールバックコードを実行すると、必要なデータがバッファに収まらなくなる可能性があります。

おすすめ記事