プログラミング言語での実装ではない場合、「システムコール」とはどういう意味ですか?


14

「システムコール」という用語を理解したいと思います。システムコールは、ユーザー空間アプリケーションからカーネルサービスを取得するために使用されることをよく知っています。

明確にする必要があるのは、「システムコール」と「システムコールのC実装」の違いです。

これは私を混乱させる引用です:

Unixライクなシステムでは、そのAPIは通常、システム呼び出しにラッパー関数を提供するglibcなどのCライブラリ(libc)の実装の一部であり、多くの場合、呼び出し元のシステム呼び出しと同じ名前が付けられます。

「彼らが呼ぶシステムコール」とは何ですか?それらのソースはどこですか?コードに直接含めることはできますか?

一般的な意味での「システムコール」はPOSIX定義のインターフェイスにすぎませんが、実際に実装を確認するにはCソースを調べ、実際のユーザー空間からカーネルへの通信が実際にどのように行われるかを確認しますか?

背景メモ:最終的に、各c関数がからのデバイスと対話するかどうかを理解しようとしています/dev

回答:


21

システムコール自体は概念です。これらは、プロセスがカーネルに実行を要求できるアクションを表します。

これらのシステムコールは、UNIXライクシステムのカーネルに実装されています。この実装(Cで書かれ、小さな部品の場合はasmで書かれている)は、実際にシステムでアクションを実行します。

次に、プロセスはインターフェイスを使用して、システムコールの実行をシステムに要求します。このインターフェイスはPOSIXで指定されています。これは、C標準ライブラリの一連の関数です。これらは実際にはラッパーであり、いくつかのチェックを実行してから、システムコールに必要なアクションを実行するようカーネルに指示するシステム固有の関数を呼び出すことができます。そして、コツは、インターフェースであるこれらの関数は、システム呼び出し自体と同じ名前が付けられ、しばしば「システム呼び出し」と直接呼ばれることです。

システム固有のメカニズムを介してシステムコールを直接実行するカーネル内の関数を呼び出すことができます。問題は、コードの移植性がまったくないことです。

したがって、システムコールは次のとおりです。

  • コンセプト、ユーザープロセスにサービスを提供するためにカーネルによって実行される一連のアクション
  • カーネルからこのサービスを取得するためにコードで使用する必要があるC標準ライブラリの機能。

1
「ラッパー関数」の例と実際のシステムコールはありますか?(Linuxのファイルパスまたはソースへのリンク)
TheMeaningfulEngineer 14

3
たとえば、これはgetpidLinuxカーネルのシステムコールの実装です:lxr.free-electrons.com/source/kernel/timer.c?v=2.6.35#L1337。そして、これはGNU C標準ライブラリglibc-2.19のラッパー関数です:fossies.org/dox/glibc-2.19/…
lgeorget 14

@Igeorget:リンクは機能しなくなりました。カーネル実装の更新されたリンク:github.com/torvalds/linux/blob/…。最近のglibcの動作を見つけることができませんでした。そのコードはナビゲートできません。
rchard2scout

6

システムコールは、プログラムは、それ自体で行うことができないことを、あなたのプログラムに代わって、いくつかの操作を行うには、オペレーティングシステム(カーネル)を依頼する方法である(あるいは単に不便です)。何らかの操作を実行できない理由は、通常、ランダムプログラムがそれらを実行できるようにすると、I / O(RAMに直接、何でも上書き)を行うなど、システムの整合性が損なわれる可能性があるためです。

POSIXは、プログラム(プログラムが呼び出すことができる特定の機能)のインターフェースを定義します。それらのいくつかは、システムコールに多かれ少なかれ直接変換されますが、他のものはより詳細な説明が必要です。これは、POSIXインターフェイスを提供し、引数をパッケージ化し、結果を呼び出し元に返す責任を持つ、Cライブラリなどの言語のランタイムです。

Unixyシステムは、POSIXインターフェイスをシステムコールとしてほぼ直接提供します。通常、システムコールを直接呼び出すsyscall(2)方法があります。Linuxでこの機能を使用する方法の詳細を探してください。


1
あなたは他の答えがちょうどブラッシュアップする重要なポイントに触れます。合理的に可能なプログラマが自分自身のために書くことができることを任意の関数(のようなstrlenstrcpysqrt、及びqsort)することができ、おそらくライブラリからロードされ、ユーザ空間です。(ほとんどがlibc。sqrt三角関数や双曲線関数などの数学関数は、おそらくlibm、数学ライブラリにあります。)…(続き)
スコット14

1
(続き)...しかし、ユーザーは自分の書くことができる方法はありませんforkkillまたはopenこれらは、オペレーティングシステムカーネルメモリ空間(例えば、プロセス・テーブル)または特権命令(例えば、I / O)へのアクセスを必要とするための機能は、。したがって、これらの機能を実行するコードはオペレーティングシステムカーネル内にある必要があります。したがって、システム関数またはシステムコール。
スコット14

5

確かに、どのように多くの方向、私たちは、この象を見ることができますか?事。

実際のシステムコールは、ビルドプログラムでは、カーネルモードへの特権エスカレーションをトリガーするマシン命令であり、カーネル自体では、命令が呼び出すコードです。libcコード(およびすべての言語ランタイム)は、カーネルコードがそれらを見つけると予想されるマシンレジスタとストレージ内パラメーターをセットアップします。

OSコード自体に入ると、ユーザーランドランタイムが行ったマシン固有の処理が少し鏡像になり、完全に通常のサブルーチン呼び出しが行われます。
本格的なOSでこれがどのように機能するかを正確に確認したい場合は、カーネルソース(git clone https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/)をプルして、などを実行しますgit grep -i system\ call。glibcソースを引き出して、同様に行います。


確かに、Linuxやglibcでうろついているのはちょっと
面倒

3

Linuxでは、少なくともシステムコールメカニズムは、特定の形式のデータ(通常は何らかのc構造体)をレジスタまたは定義済みメモリアドレスに配置することで、ほとんどのアーキテクチャで機能します。

ただし、問題は実際にCPUにカーネルスペースへの切り替えを強制し、特権カーネルコードを実行して呼び出しを処理できるようにすることです。これは、ある種の障害(0による除算、未定義のオーバーフロー、またはセグメンテーション違反など)を強制することで行われ、これにより、カーネルが強制的に実行を引き継いで障害を処理します。

通常、カーネルは原因となっているプロセスを強制終了するか、ユーザー提供のハンドラーを実行することで障害を処理します。ただし、syscallの場合、代わりに事前定義されたレジスタとメモリの場所をチェックし、syscall要求が含まれている場合は、メモリ内構造体のユーザープロセスによって提供されたデータを使用して実行します。これは通常、特別に手作りされたアセンブリを使用して実行する必要があり、ユーザーのsyscallの使用を容易にするために、システムのCライブラリはそれを関数としてラップする必要があります。下位レベルのインターフェイスについては、syscallの動作方法と、Cラッパーなしでそれを呼び出す方法に関する情報については、http: //man7.org/linux/man-pages/man2/syscall.2.html を参照してください

これは単純化されすぎており、すべてのアーキテクチャに当てはまるわけではなく(mipsには特別なsyscall命令があります)、必ずしもすべてのOSで同じように動作するわけではありません。それでも、コメントや質問がある場合はお問い合わせください。

修正済み:/ dev /にあるものについてのコメントに関して、これは実際にはカーネルに対するより高いレベルのインターフェースであり、低いインターフェースではありません。これらのデバイスは、実際に(約)4つのシステムコールを下で使用します。それらへの書き込みは、書き込みシステムコール、読み取りシステムコールの読み取り、オープンおよびクローズシステムコールと同等のオープン/クローズ、およびioctlの実行と同じであり、システムの多くのioctlの1つにアクセスするためのインターフェースである特別なioctl syscallを引き起こします呼び出し(特別な、通常は使用量が狭すぎてシステムコール全体を記述できないデバイス固有の呼び出し)。


1

各システムコールには整数が関連付けられています。この整数は、システムコールの戻り値、システムコールへの引数の数、および引数のタイプの関数です。このシステムコール番号は、グローバルシステムコールベクトルへのオフセットにすぎません。特権モードでのみアクセス可能なこのベクトルには、適切なハンドラへのポインタが含まれています。システムコールを呼び出す際のプロセスでは、ソフトウェア割り込み(トラップ割り込み)が生成されるため、どのシステムコールを呼び出すかを決定するトラップハンドラが実行されます。次に、カーネルは、スタック上にあるユーザーから渡されたシステムコールの引数をプロセッサレジスタにコピーし、要求されたサービスが完了すると、データはプロセッサレジスタからスタックにコピーされます。これが、システムコールに対する引数が限られている理由の1つです。


各呼び出し(操作)は、trueという数値によって内部的に識別されます。ただし、その数は戻り値や引数の数ではなく、操作に依存します。x86でユーザーランドからどのように機能していたかについての説明はこちら
vonbrand
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.