コンピューター ソフトウェアは、一部のタスクを自動化したり、一部の問題を解決したりするために開発されています。いずれにせよ、ソフトウェアは、そのソフトウェアの開発者が記述したロジックの助けを借りて目標を達成します。すべてのロジックには、文字列の長さの計算、ファイルのオープンなどのサービスが必要です。標準サービスは、この目的のみに提供される関数または呼び出しによって提供されます。
文字列の長さの計算と同様に、ファイルを開くには、strlen() などの標準関数があり、open() や fopen() などの関数があります。これらの関数は、どのアプリケーションでも使用できるため、標準関数と呼んでいます。
これらの標準機能は、次の 2 つの主要なカテゴリに分類できます。
<オール>この記事では、システム コールとライブラリ コールの背後にある概念についてさまざまな点で説明し、必要に応じて 2 つの違いを説明します。
1.ライブラリ関数とシステム コール
標準 C ライブラリの一部である関数は、ライブラリ関数として知られています。たとえば、strcmp()、strlen() などの標準的な文字列操作関数はすべてライブラリ関数です。
プログラムの実行モードをユーザー モードからカーネル モードに変更する関数は、システム コールと呼ばれます。これらの呼び出しは、カーネルからのプログラムがいくつかのサービスを必要とする場合に必要です。たとえば、システムの日付と時刻を変更したい場合、またはネットワーク ソケットを作成したい場合、これらのサービスはカーネルによってのみ提供されるため、これらのケースではシステム コールが必要になります。たとえば、socket() はシステム コールです。
2.システム コールが必要な理由
システム コールは、OS カーネルへのエントリ ポイントとして機能します。プロセスがカーネル モードで実行されている場合にのみ実行できる特定のタスクがあります。これらのタスクの例としては、ハードウェアなどとの対話があります。したがって、プロセスがそのような種類のタスクを実行したい場合は、システム コールによって可能になるカーネル モードで実行する必要があります。
3.ライブラリ関数の種類
ライブラリ関数には 2 つのタイプがあります:
- システム コールを呼び出さない関数
- システム コールを行う関数。
システムコールを行わないライブラリ関数があります。たとえば、strlen() などの文字列操作関数はこのカテゴリに分類されます。また、さらにシステム コールを行うライブラリ関数もあります。たとえば、fopen() 関数は標準ライブラリ関数ですが、内部では open() システム コールを使用します。
4.コンポーネント間の相互作用
次の図は、ライブラリ関数、システム コール、アプリケーション コードがどのように相互作用するかを示しています。
上の図は、アプリケーション コードがライブラリ関数またはシステム コールと対話できることを明確に示しています。また、ライブラリ関数はシステム関数を内部から呼び出すこともできます。ただし、カーネルにアクセスできるのはシステム コールだけであり、カーネルはさらにコンピュータ ハードウェアにアクセスできます。
5. fopen() と open() の比較
ファイルを開くという同じ操作に対して 2 つの関数があるのはなぜでしょうか?
これに対する答えは、fopen() はファイルを開くためのバッファ付き I/O サービスを提供するライブラリ関数であり、open() はバッファなし I/O サービスを提供するシステム コールであるという事実です。 open() 関数もアプリケーションで使用できますが、アプリケーションで直接使用することは避けてください。
一般に、システム コールに対応するライブラリ関数が存在する場合、次の理由により、アプリケーションはライブラリ関数を使用する必要があります。
- ライブラリ関数は移植可能です。つまり、標準ライブラリ関数を使用するアプリケーションはすべてのシステムで実行されます。一方、対応するシステム コールに依存するアプリケーションは、システム コール インターフェイスがシステムごとに異なる可能性があるため、すべてのシステムで実行されるとは限りません。
- 対応するライブラリ関数によって、システム コールへの負荷が軽減され、ユーザー モードからカーネル モードへの切り替えが頻繁に行われないことがあります。たとえば、ファイルからデータを頻繁に読み取るアプリケーションがある場合、read() の代わりに fread() を使用すると、バッファリングされた I/O が提供されます。つまり、fread() を呼び出すたびにシステム コール read が呼び出されるわけではありません。 (). fread() は、(ユーザーが必要とするよりも) 大量のデータを一度に読み取ることができるため、後続の fread() はシステム関数 read() の呼び出しを必要としません。
6. malloc() はシステム コールですか?
これは、人々が持っている非常に一般的な誤解の 1 つです。 malloc() がシステムコールではないことを明確にしましょう。関数呼び出し malloc() は、さらにメモリ割り当てのために brk() または sbrk() システム コールを使用するライブラリ関数呼び出しです。
7.システム コール :実行モードの切り替え
従来、「int $0x80」の割り込みをカーネルに発生させるメカニズムが使用されていました。割り込みをトラップした後、カーネルはそれを処理し、実行モードをユーザー モードからカーネル モードに変更します。現在、実行モードの切り替えには systenter/sysexit 命令が使用されています。
8.その他の違い
上記のすべてに加えて、システム呼び出しとライブラリ呼び出しの違いがいくつかあります:
- ライブラリ関数はユーザー プログラムにリンクされ、ユーザー空間で実行されますが、システム コールはユーザー プログラムにリンクされず、カーネル空間で実行されます。
- ライブラリ関数の実行時間はユーザー レベル時間にカウントされ、システム コールの実行時間はシステム時間の一部としてカウントされます。
- ライブラリ関数はデバッガを使用して簡単にデバッグできますが、システム コールはカーネルによって実行されるためデバッグできません。