Linuxのライブラリ関数とシステムコールの間の差との関係
先週、彼女はによる「システムを呼び出す」、実際には、これらの関数の対応する機能を実現することができ、「基本的なIO C標準ライブラリ」をまとめました。この記事は、各システムコールインタフェースの詳細の使用状況にはなく、「ライブラリ関数」および「システム」コールの間の関係との違いについての深い理解に意図されていません。
まず、システムコール
システムコールは、我々は、オペレーティングシステムがハードウェアデバイスの機能に、オペレーティング・システム・インタフェースを提供するインタフェースの一連の操作(API)、をユーザに提供することを理解することができます。それは例えば、我々が最も精通している、より抽象的であるかもしれない hello world
画面上の情報をプリントアウトするプログラム。呼び出すとき printf()
の関数を、および関数ライブラリは printf
、基本的にシステムコールの呼び出しで write()
印刷機能端末情報を達成するための機能。
第二に、ライブラリ関数
ライブラリ関数は、層のシステムコールのパッケージとして理解することができます。ユーザプログラムにカーネルによって提供されるシステムコールインタフェースは、その効率はより効率的で合理化され、時には我々は、情報へのアクセスを必要とする、より複雑な処理、またはより人間的なニーズである、我々はにパッケージ化、これらのプロセスを置きますプログラマと機能に供給され、プログラムが容易猿コーディング。
ライブラリ関数は、システムコールが含まれている可能性があり、それはいくつかのシステムコールを有することが可能であり、当然のことながら、例えば、いくつかの操作は、コアの機能を伴わない、何のシステムコールが存在しない場合があります。あなたは、ライブラリ関数とシステムコールの間の関係を理解するために、次の図を参照することができます。
第三に、システムが意味を呼び出します
- 基盤となるハードウェア上で直接プログラムするユーザーを避けるために。例えば、最も簡単な
hello world
手順は端末に情報を印刷することで、端末は、システムのハードウェアリソース、そうでない場合は、システムコールで、ユーザプログラムは、自分の端末装置を書くだけでなく、コードが端末に表示方法を制御するドライバが必要です。 - 技術的な詳細の後ろに隠れます。そのようなあなたは、ディスクのどのトラックとセクタのデータを心配することなく、システムコール、ユーザプログラムを使用して、データがどのような位置をメモリにロードする場合、ファイルの読み書きなど。
- システムのセキュリティと安定性を確認してください。直接基礎となるデータカーネルに直接アクセスすることは、そのような駆け出しのプログラム猿のようにカーネルアドレス空間を、操作する彼を任せることはできないユーザプログラムを知るためには、カーネルのセキュリティシステムは保証されません。システム機能は、ユーザーが唯一、細部を気にすることなく、インターフェースを呼び出す必要がカーネルによって実装されているだけでなく、セキュリティシステムのリスクを避けるために呼び出します。
- プログラムの移植を容易にします。もし、リソースのためのオペレーティングシステムの機能のような書き込み()、我々はすべて、我々は移植手順が非常に悪くなる書き出す、これを達成するために自分のアイデアに従ってください。
すべてのすべてで、私たちは便利で安全な、システムコールインタフェースとして、このインターフェイスは、当社の機能を実現することができます必要があります。
第四に、システムコールVSライブラリ関数
「Cプログラミングの専門家」A.4付録参考図書は、本についての質問に答えるために、2つの間のこのような差がある、ライブラリコールは、言語やアプリケーションの一部であり、システムコールは、オペレーティングシステムの一部です。
- すべてのCライブラリは同じであり、システムは、各オペレーティングシステムが異なっている呼び出します。
- ライブラリの呼び出しは、関数ライブラリを呼び出すプログラムであり、カーネルのシステムコールは、サービスの呼び出しです。
- Library呼び出しは、ユーザプログラムにリンクされ、そしてシステムコールは、エントリのポイントのオペレーティングシステムであるされています
- Library呼び出しは、ユーザーのアドレス空間で実行され、システムコールはカーネルアドレス空間で実行されています
- ライブラリ呼び出しは、「ユーザー」の時間に属する-時間を実行し、実行時のシステムコールが所属する「システム」の時間に
- プロシージャ・コールのオーバーヘッドを所属Library呼び出しが小さく、かつ、大きなオーバーヘッド切り替え、その後、システムコールカーネルコンテキストに切り替えるとする必要性
- UNIXには約300のプログラムlibcのCライブラリでは、約90のシステムコールがあります
- 典型的なCライブラリ関数:システム、fprintfの、malloc関数、及び典型的なシステムコール:CHDIR、フォークを、書き込み、BRK
本の記録によると、ライブラリ・コールが約半分に微妙な時間がかかり、システムコールとコンテキストのオーバーヘッドは、システムのカーネルを切り替えるために必要な時間は、約70倍(35秒)ライブラリ関数の呼び出しでは、呼び出します。純粋にパフォーマンス上からは、システムの数を減らす必要があり、できるだけ多くを呼び出しますが、あなたは多くのC関数ライブラリプログラムは、システムコールを通じて機能を実装することを覚えておく必要があります。
第五に、システムコールライブラリ関数の正しい理解を効率的に
まず説明し、パフォーマンス、上記のライブラリ関数は、システムの前提は、システムコールを使用せずにライブラリ関数のようなものを呼び出すよりもはるかに高いです。ここでも、いくつかのライブラリ関数は、システムコールを含ん説明が、それは、より高いパフォーマンスのシステムコールを持っています。例えば、これらのライブラリ関数は、システムコールの数を減らすために、バッファを使用しているため、これらの機能のパフォーマンスは、システムコールよりも確かに高いです通常の状況下では、ファイルIO関数のfread、fwriteの、FPUTC、fgetc関数などの最後の記事では、パフォーマンスを思われます比較的高いです。
第六に、どのようにシステムコールを実行することです
明確なライブラリ関数とシステムコール、およびそれらの間の関係の基本的な考え方の上に、のは、それがどのように機能するか最終的にはシステムコールがあることを理解しましょう。
プロセスが実行されている場合、割り込みが発生し、ファイル操作を読み書きするために会った、システムが割り込み後にカーネルスタックに保存されている現在のユーザーのプロセス情報の一部、割り込みサービスルーチンを登録し、その後、ここに対処するためのシステムコールを実行しようとしています、Linuxの実行によって int $0x80
割り込みシステムコールを実行するために、しかし、カーネルはシステムコールの数を実装し、次にあなたが通過する必要のあるシステムコールを示すために必要な「システムコール」。
ためにはより明確にシステムコールのプロセスを説明するために、私たちここでは、システムコールを実装するために、コードのオンライン部分を参照してください。
INT メイン() { のtime_t TT。 構造体のtm *のトン。 ASM 揮発性( "$ 0楽章%% EBXの\ n個の\ tの" " のmov $の0xdを、%% EAXの\ n個の\ tの" " int型$ 0x80の\ nは\ tの" " MOV %% eaxに、%0 \ nは\ tの" :" = M " (TT) )。 T = LOCALTIME(&TT)。 printf(" 時間:%D-%02d-%02D%02D:%02D:%02Dのn \ " 、 T - >のtm_year + 1900 、 T - >、T-> tm_mday、 T - > tm_hour、T-> tm_min、T-> のtm_sec)。 } [ホスト@ linuxblogs〜]はgccの交流-oa && ./ $ 時間:2018年 - 05 - 06 03:23:46
まず、 mov $0xd %%eax
システムにコールに %eax
レジスタ、時間()システムコール番号が実行次いで、13で int $0x80
、システムは時間に()システムコールを実行します。実際には、コードの一部が時間を実現するためにコンパイルされている()システムコール機能、アセンブリコードは、明確なシステムコールのプロセス全体ことを確認するために、主にここで、(私は理解していない)問題ではありません理解していません。
先週、彼女はによる「システムを呼び出す」、実際には、これらの関数の対応する機能を実現することができ、「基本的なIO C標準ライブラリ」をまとめました。この記事は、各システムコールインタフェースの詳細の使用状況にはなく、「ライブラリ関数」および「システム」コールの間の関係との違いについての深い理解に意図されていません。
まず、システムコール
システムコールは、我々は、オペレーティングシステムがハードウェアデバイスの機能に、オペレーティング・システム・インタフェースを提供するインタフェースの一連の操作(API)、をユーザに提供することを理解することができます。それは例えば、我々が最も精通している、より抽象的であるかもしれない hello world
画面上の情報をプリントアウトするプログラム。呼び出すとき printf()
の関数を、および関数ライブラリは printf
、基本的にシステムコールの呼び出しで write()
印刷機能端末情報を達成するための機能。
第二に、ライブラリ関数
ライブラリ関数は、層のシステムコールのパッケージとして理解することができます。ユーザプログラムにカーネルによって提供されるシステムコールインタフェースは、その効率はより効率的で合理化され、時には我々は、情報へのアクセスを必要とする、より複雑な処理、またはより人間的なニーズである、我々はにパッケージ化、これらのプロセスを置きますプログラマと機能に供給され、プログラムが容易猿コーディング。
ライブラリ関数は、システムコールが含まれている可能性があり、それはいくつかのシステムコールを有することが可能であり、当然のことながら、例えば、いくつかの操作は、コアの機能を伴わない、何のシステムコールが存在しない場合があります。あなたは、ライブラリ関数とシステムコールの間の関係を理解するために、次の図を参照することができます。
第三に、システムが意味を呼び出します
- 基盤となるハードウェア上で直接プログラムするユーザーを避けるために。例えば、最も簡単な
hello world
手順は端末に情報を印刷することで、端末は、システムのハードウェアリソース、そうでない場合は、システムコールで、ユーザプログラムは、自分の端末装置を書くだけでなく、コードが端末に表示方法を制御するドライバが必要です。 - 技術的な詳細の後ろに隠れます。そのようなあなたは、ディスクのどのトラックとセクタのデータを心配することなく、システムコール、ユーザプログラムを使用して、データがどのような位置をメモリにロードする場合、ファイルの読み書きなど。
- システムのセキュリティと安定性を確認してください。直接基礎となるデータカーネルに直接アクセスすることは、そのような駆け出しのプログラム猿のようにカーネルアドレス空間を、操作する彼を任せることはできないユーザプログラムを知るためには、カーネルのセキュリティシステムは保証されません。システム機能は、ユーザーが唯一、細部を気にすることなく、インターフェースを呼び出す必要がカーネルによって実装されているだけでなく、セキュリティシステムのリスクを避けるために呼び出します。
- プログラムの移植を容易にします。もし、リソースのためのオペレーティングシステムの機能のような書き込み()、我々はすべて、我々は移植手順が非常に悪くなる書き出す、これを達成するために自分のアイデアに従ってください。
すべてのすべてで、私たちは便利で安全な、システムコールインタフェースとして、このインターフェイスは、当社の機能を実現することができます必要があります。
第四に、システムコールVSライブラリ関数
「Cプログラミングの専門家」A.4付録参考図書は、本についての質問に答えるために、2つの間のこのような差がある、ライブラリコールは、言語やアプリケーションの一部であり、システムコールは、オペレーティングシステムの一部です。
- すべてのCライブラリは同じであり、システムは、各オペレーティングシステムが異なっている呼び出します。
- ライブラリの呼び出しは、関数ライブラリを呼び出すプログラムであり、カーネルのシステムコールは、サービスの呼び出しです。
- Library呼び出しは、ユーザプログラムにリンクされ、そしてシステムコールは、エントリのポイントのオペレーティングシステムであるされています
- Library呼び出しは、ユーザーのアドレス空間で実行され、システムコールはカーネルアドレス空間で実行されています
- 函数库调用的运行时间属于「用户」时间,而系统调用的运行时间属于「系统」时间
- 函数库调用属于过程调用,开销较小,而系统调用需要切换到内核上下文环境然后切换回来,开销较大
- 在C函数库libc中大约 300 个程序,在 UNIX 中大约有 90 个系统调用
- 函数库典型的 C 函数:system, fprintf, malloc,而典型的系统调用:chdir, fork, write, brk
据书中记载,库函数调用大概花费时间为半微妙,而系统调用所需要的时间大约是库函数调用的 70 倍(35微秒),因为系统调用会有内核上下文切换的开销。纯粹从性能上考虑,你应该尽可能地减少系统调用的数量,但是,你必须记住许多 C 函数库中的程序通过系统调用来实现功能。
五、正确理解库函数高效于系统调用
首先解释,上述说明的库函数性能远高于系统调用的前提是,库函数种没有使用系统调用。再来解释下某些包含系统调用的库函数,然而其性能确实也要高于系统调用。比如上篇文章中关于文件 IO 函数 fread、fwrite、fputc、fgetc 等,这些函数通常情况下性能确实比系统调用高,原因在于这些库函数使用了缓冲区,减少了系统调用的次数,因而显得性能比较高。
六、系统调用是如何运行的
上述内容基本说清楚了库函数与系统调用的概念以及它们之间的关系,下面我们来理解系统调用到底是如何运行的。
当一个进程正在运行,遇到读写文件操作,会发生一个中断,中断后系统会把当前用户进程的一些寄存器信息保存在内核堆栈中,接着去处理中断服务程序,这里是要去执行系统调用,Linux 中通过执行 int $0x80
来执行系统调用的中断,但内核实现了很多系统调用,这时需要传递「系统调用号」来指明需要哪个系统调用。
为了更清楚的说明系统调用的过程,我们这里参考网上的一段代码来实现系统调用:
int main() { time_t tt; struct tm *t; asm volatile ( "mov $0,%%ebx\n\t" "mov $0xd,%%eax\n\t" "int $0x80\n\t" "mov %%eax,%0\n\t" : "=m" (tt) ); t = localtime(&tt); printf("Time: %d-%02d-%02d %02d:%02d:%02d\n", t->tm_year + 1900, t->tm_mon + 1、T-> tm_mday、 T - > tm_hour、T-> tm_min、T-> のtm_sec)。 } [ホスト@ linuxblogs〜]はgccの交流-oa && ./ $ 時間:2018年 - 05 - 06 03:23:46
まず、 mov $0xd %%eax
システムにコールに %eax
レジスタ、時間()システムコール番号が実行次いで、13で int $0x80
、システムは時間に()システムコールを実行します。実際には、コードの一部が時間を実現するためにコンパイルされている()システムコール機能、アセンブリコードは、明確なシステムコールのプロセス全体ことを確認するために、主にここで、(私は理解していない)問題ではありません理解していません。