回答:
実際、システムコールには3つの段階があります。
getpid
、gettimeofday
、getuid
またはsetuid
。一部のシステムコールは、状況に応じてブロックまたは非ブロックになります。たとえばread
、ファイルがパイプまたは非ブロッキング読み取りをサポートする他のタイプであり、O_NONBLOCK
フラグが設定されている場合はブロックしません。sleep
です。read
、ブロッキングファイル記述子で呼び出されるのはブロッキングであり、そうですwait
。「高速」システムコールと「低速」システムコールの違いは、ノンブロッキングとブロッキングに近いですが、今回はカーネル実装者の観点から見てください。高速システムコールとは、ブロックまたは待機せずに完了できることが知られているシステムコールです。カーネルは、高速のシステムコールに遭遇すると、すぐにシステムコールを実行し、同じプロセスをスケジュールできることを認識します。(非プリエンプティブマルチタスクを使用する一部のオペレーティングシステムでは、高速のシステムコールはプリエンプティブではない場合があります。これは通常のUNIXシステムには当てはまりません。)呼び出しプロセスを一時停止し、別のタスクを実行する準備をする必要があります。
いくつかのケースは少し灰色の領域です。たとえば、(read
通常のファイルからの)ディスク読み取りは、別のプロセスを待機していないため、通常は非ブロッキングと見なされます。ディスクを待つだけで、通常は答えるのにほんの少しの時間しかかかりませんが、永遠にはかかりません(したがって、上記のケース2になります)。しかし、カーネルの観点から見ると、プロセスはディスクドライバーが完了するまで待機する必要があるため、間違いなく遅いシステムコールです。
O_NONBLOCK
フラグの状態に応じて両方を持つことができます。フラグが設定されている場合、システムコールは他の何も待たずに完了できるため、非ブロッキングであり、カーネルはそれを高速システムコールとして扱うことができます。
遅いシステムコールは、TCPソケットread()のようなものです-O_ASYNC(または何でも)が設定されていない場合、それは永遠に待機できます。
高速システムコールはgettimeofday()やgetpid()のようなもので、どちらもカーネルがすぐに利用できるプロセスに情報を返します。
ディスク読み取りは、遅いシステムコールのカテゴリに分類されます。プロセスが真のディスクファイル、ファイル記述子でread()を実行する場合、カーネルは読み取りを満たすために1つ以上のディスクブロックを読み取る必要がある場合があります。基盤となるファイルシステムのディスク上の構造に応じて、これはディスク上のiノードを読み取って「間接ブロック」のディスクブロック番号を取得し、間接ブロックを読み取ってデータブロックを取得してから、データブロック自体を読み取ることを意味する場合があります。少なくともディスクアクセスあたりのCPUサイクルの観点では、かなり時間がかかりますが、今日は古き良き時代よりもひどいでしょう。
私はこれを昔から見ていませんが、古いUnixディスクドライブのデバイスドライバーコードの「下半分」は、ディスク上のファイルシステムの整合性を維持しやすくするために、信号/割り込みをブロックします。場合によっては、バグのあるドライバーや障害のあるディスクが、プロセスが要求したディスクブロックをまったく送信せず、プロセスが永久にスリープすることがありました。-9を殺しても何もしませんでした。