web-dev-qa-db-ja.com

write()とprintf()の違い

最近私はオペレーティングシステムを勉強しています..私は知りたいだけです:

システムコール(write()など)と標準ライブラリ関数(printf()など)の違いは何ですか?

13
CSnerd

システムコールは、アプリケーションの一部ではないがカーネル内にある関数の呼び出しです。カーネルは、ハードウェアを抽象化するためのいくつかの基本的な機能を提供するソフトウェア層です。大まかに言って、カーネルはハードウェアをソフトウェアに変えるものです。

最終的には常にwrite()を使用して、書き込むデバイスの種類に関係なく、周辺機器に何かを書き込みます。 write()は、のみバイトのシーケンスを書き込むように設計されています。これですべてです。ただし、write()は基本的すぎると見なされるため(10単位で整数を記述したり、科学的記数法で浮動小数点数を記述したりすることもできます)、さまざまな種類のプログラミング環境からさまざまなライブラリが提供されます。君は。

たとえば、Cプログラミング言語では、さまざまな形式でデータを書き込むことができるprintf()が提供されます。したがって、printf()は、データをフォーマットされたバイトシーケンスに変換し、write()を呼び出してそれらのバイトを出力に書き込む関数として理解できます。しかし、C++はあなたにcoutを与えます。 Java _System.out.println_など。これらの各関数は、write()の呼び出しで終了します(少なくともPOSIXシステムでは)。

知っておくべきことの1つ(重要)は、そのようなシステムコールはコストがかかるということです!自分のコードの外にあるものを呼び出す必要があり、システムは厄介なことなどをしようとしていないことを確認する必要があるため、これは単純な関数呼び出しではありません。したがって、高次の印刷のような関数では、バッファリングが組み込まれています。書き込みが常に呼び出されるとは限りませんが、データは隠された構造に保持され、本当に必要または必要な場合にのみ書き込まれます(バッファーがいっぱいであるか、印刷の結果を本当に確認したい場合)。

これはまさにあなたがあなたのお金を管理するときに起こることです。多くの人があなたにそれぞれ5ドルを与えるならば、あなたはそれぞれを銀行に預金することはありません!あなたはそれがいっぱいになるまであなたの財布(これはprintです)にそれらを保持します、またはあなたはそれらをもう保持したくありません。それからあなたは銀行に行き、大きな預金をします(これは書き込みです)。そして、あなたはあなたの財布に5ドルを置くことは銀行に行って預金をするよりはるかに速いことを知っています。バンクはカーネル/ OSです。

57

システムコールはオペレーティングシステムによって実装され、カーネルモードで実行されます。ライブラリ関数は、アプリケーションコードと同様に、ユーザーモードで実装されます。ライブラリ関数はシステムコールを呼び出す場合があります(たとえば、printfは最終的にwriteを呼び出します)が、それはライブラリ関数の目的によって異なります(数学関数は通常カーネルを使用する必要はありません)。

1
Barmar

OSのシステムコールは、OSとの対話に使用されます。例えば。 Write()は、システムまたはプログラムで使用できます。

標準ライブラリ関数はプログラム固有ですが、たとえば、 printf()は何かを出力しますが、GUI /コマンドラインにのみ表示され、システムには影響しません。

コメントするには50の評判が必要なので、コメントできませんでした。

編集:バーマーは良い答えを持っています

1
smushi

printf()は、Cライブラリから関数を呼び出すためにユーザースペースに公開されるAPIまたはインターフェイスの1つです。

printf()は実際にはwrite()システムコールを使用します。 write()システムコールは、実際にはデータを出力に送信する役割を果たします。

0
Syed.Waris

私は小さなプログラムを書いています。現時点では、stdinから各行を読み取り、stdoutに出力します。ループ内に書き込む呼び出しを追加すると、各行の最後に数文字が追加されます。しかし、代わりにprintfを使用すると、余分な文字はすべてクラスター化され、各行に表示されるのではなく、一度に表示されます。

Printfを使用すると、stderrがバッファリングされるようです。 printfを呼び出した後にfflush(stdout);を追加すると、出力の不一致が修正されます。

0
Rolf

stdioバッファはプロセスのユーザー空間メモリに保持され、システムコールwriteはデータをカーネルバッファに直接転送するというもう1つのポイントに言及したいと思います。つまり、forkwriteの呼び出しの後にprintfプロセスを実行すると、フラッシュによって、行バッファリングとブロックバッファリングの対象となる3回の出力が発生する可能性があります。 printfバッファは子でstdioによって複製されるため、これらはfork呼び出しに属します。

0
snr