ホームページ  >  記事  >  バックエンド開発  >  システムコールの目的は何ですか

システムコールの目的は何ですか

晓曦&sea
晓曦&seaオリジナル
2020-07-16 17:44:1710649ブラウズ

システム コールの目的は、システム サービスを要求することです。オペレーティング システムでは、ユーザーがさまざまなハードウェア リソースを直接操作することはできないため、ユーザー プログラムはシステム コールを通じてカーネルにサービスを要求し、さまざまなリソースを間接的に使用することしかできません。

システムコールの目的は何ですか

#オペレーティング システムによって提供される機能は、通常、アプリケーション自体によって実装されません。たとえば、周辺機器を直接管理する権限を持っているのはオペレーティング システムだけであるため、ファイルを操作するにはアプリケーションがシステム コールを行う必要があります。もう 1 つの例は、プロセスまたはスレッド間の同期相互排他操作です。これも、カーネル変数を維持するためにオペレーティング システムによって完了する必要があります。

完全なコンピューター システムを下から上に見てみましょう: 物理ハードウェア -> OS カーネル -> OS サービス -> アプリケーション。ここでの OS カーネルは、「前のものを次のものに接続する」という重要な役割を果たし、下位では物理ハードウェアを管理し、上ではオペレーティング システムのサービスとアプリケーションのインターフェイスを提供します。ここでのインターフェイスはシステム コールです。

アプリケーション プロセスは通常、ユーザー モードで実行されます。システム コールを呼び出すと、プロセスはカーネル モードに入り、カーネル内のコードを実行します。これにより、特権命令を実行し、特定の機能を完了する権限が与えられます。言い換えれば、システム コールは、アプリケーションがオペレーティング システム カーネルに能動的に入る入り口です。

1. システムコールとライブラリ関数の違い

ライブラリ関数

名前の通り、関数が配置されています。これは、一般的に使用されるいくつかの関数をコンパイルし、他の人が使用できるようにファイルに配置することです。他の人がそれを使用する場合は、#include を使用してファイル名を追加するだけです (通常は lib ファイル内)。

ライブラリ機能は主に 2 つのパーティによって提供されます。1 つはオペレーティング システムによって提供され、もう 1 つはサードパーティによって提供されます。

  • システムによって提供されるこれらの関数は、システム コールをカプセル化または結合して、より多くの機能を実現します。このようなライブラリ関数は、カーネルにとってより複雑な一部の操作を実装できます。たとえば、読み取り関数はパラメータに基づいてファイルを直接読み取ることができますが、その背後にある隠しファイル(どのトラック、どのセクタ、どのメモリにロードされるかなど)は、プログラマが気にする必要のない問題です。これらの操作にはシステム コールも含まれます。たとえば、write() システム関数は、同じ名前のシステム コールを呼び出して、書き込み操作を完了します。

  • サードパーティ ライブラリの場合、システム コールを直接使用する可能性が低く、システムが提供する API インターフェイスを通じて実装される点を除けば、実際にはシステム ライブラリと同じです。 。たとえば、printf は実際には write() システム関数を呼び出します。サードパーティのライブラリ関数のほとんどは、システム関数のカプセル化です。

システム コールとライブラリ関数の関係:

実際、システム コールがユーザーに提供するものは次のとおりです。純粋な高度なサービスについては、よりユーザーフレンドリーで特定の状況に適した機能を持たせたい場合は、ユーザー自身が定義する必要があるため、一部のシステムコールをラップするライブラリ関数が派生します。たとえば、C 言語で文章を印刷したい場合、ライブラリ関数 printf を使用しない場合、それを自分で実装し、putc() や write() などのシステム関数を呼び出す必要があります。それはさらに面倒に思えるので、システムコールはオペレーティングシステムのインターフェースを使用するための利便性のためのものであり、ライブラリ関数は人々がプログラミングするための便宜のためのものです。

たとえば、Linux オペレーティング システムでは、C 言語ライブラリ関数 printf は実際に write システム コールを使用しますが、ライブラリ関数 strcpy (文字列コピー) はシステム コールを使用しません。さらに、システムのシステム コール インターフェイスは、通常、必要なすべての機能を完了できる最小のセットであり、同じシステム コールをカプセル化する複数のライブラリ関数が存在する場合があります。たとえば、Linux では、malloc、calloc、free の 3 つのライブラリ関数はすべて、brk システム コールを呼び出すことで完了します。

アプリケーション プログラム、ライブラリ関数、システム コールの関係を次の図に示します。

システムコールの目的は何ですか

システム コールの違いおよびライブラリ関数:

ライブラリ関数呼び出しは言語またはアプリケーションの一部ですが、システム呼び出しはオペレーティング システムの一部です。

システム コールは、アプリケーションがカーネルと対話するためのインターフェイスです。長期にわたるプログラミングでは、システム関数の使用にはプログラムの移植性という大きな欠点があることがわかりました。例えば、Linuxが提供するシステムコール関数はWindowsとは異なります。

ライブラリ関数呼び出しは、アプリケーションの API に相当するアプリケーション開発を目的としています。この方法を使用する理由は次のとおりです。

  • ダブル バッファリング テクノロジ (ライブラリ関数)およびシステム コール 2 層バッファリング、システム コールの数を削減)
  • #移植性 (一貫した外部インターフェイスを使用して、さまざまなオペレーティング システムのシステム機能をカプセル化)
  • 基盤となる呼び出し自体にいくつかの欠陥があります。
  • API にもレベルと特殊な作業指向を持たせる;

2. CPU カーネル モードとユーザー モード

通常、プロセッサには「ユーザー モード」と「カーネル モード」の 2 つのモードがあり、現在どちらのモードにあるかを識別するためにタグ ビットが使用されます。カーネル モードは、特権命令 (主にベース アドレス レジスタの内容を変更する命令などの一部のハードウェア管理命令) を含むすべての命令を実行できますが、ユーザー モードは特権命令を実行できません。この設計は主にセキュリティの問題を目的としています。つまり、上位層アプリケーションの誤った設計によって引き起こされるハードウェアの問題を回避するために、オペレーティング システムがハードウェアを管理する責任があります。

オペレーティング システムだけがハードウェアを直接操作できるため、オペレーティング システムはアプリケーションにハードウェア機能へのアクセスを提供するインターフェイスを提供する必要があります。これらのインターフェイスはシステム コールと呼ばれます。

オペレーティング システムがシステム コール要求を受信すると、プロセッサはカーネル モードに入り、I/O 操作などの命令を実行し、ベース アドレス レジスタの内容を変更します。システム コールの内容を処理した後、 、操作 システムはプロセッサをユーザー モードに戻し、ユーザー コードを実行します。

CPUのカーネルモードとユーザーモードに対応し、プロセスの実行状態はチューブステート(コアステート)とアイステート(ユーザーステート)に分けられます。詳細については、次の記事を参照してください: オペレーティング システム - ユーザー モードとコア モード

4. システム コールと割り込みの関係

割り込み(割り込み) これは通常、CPU の内部または外部で保留中のイベントが発生することを意味するため、CPU はそのようなイベントを処理するために現在の命令の実行順序を変更する必要があります。割り込みとシステムコールの関係を紹介する前に、まず割り込みを分類してみましょう。

割り込みは、大きく 2 つのカテゴリに分類できます。

  • 非同期割り込み (外部割り込み) : CPU の外部の他のハードウェアによって生成される、たとえば次のようになります。クラス割り込みは非同期です。つまり、割り込み信号はいつでも発行でき、CPU 自体のクロック ビートとは関係がありません。クロックの中断、ハードディスクの読み書きサービス要求の中断など。

  • 同期割り込み (内部割り込み/例外): CPU 内部で生成され、このタイプの割り込みは同期であると言われます。割り込み信号は、命令の実行が完了した後の現在時刻である必要があります。一般に、これらは CPU の内部イベント、または不正なオペコード、範囲外のアドレス、浮動小数点オーバーフローなどのプログラム実行中のイベントから発生します。

同期割り込み (例外) は、次のカテゴリに分類されます。

  • プロセッサによって検出された例外 : プロセッサはゼロ除算演算などの命令の実行中に検出された割り込み。

  • 障害: 異常な状態が発生しますが、異常な状態が解消されると、元のプログラム フローはページ フォールト異常などの影響を受けることなく実行を継続できます。 。割り込みをトリガーした命令が再実行されることに注意してください。

  • トラップ: トラップされた命令によって引き起こされる割り込み。通常はプログラムのデバッグに使用されます。

  • 中断: ハードウェア エラーやシステム テーブル値のエラーなど、CPU 内で重要なエラーが発生しました。この中断が発生すると、エラーは回復できなくなり、現在のプロセスを終了することしかできなくなります。

  • プログラムされた例外: ソフトウェア割り込み (ソフト割り込み) とも呼ばれ、プログラマのコードによってアクティブに開始される割り込みで、システム コールの実装に使用されます。 。たとえば、Linux では、システム コールの実装に int 0x80 命令が使用されます。

これまで、割り込みとシステム コールの関係を発見しました。 システム コールは特殊な種類の割り込み (ソフト割り込み) です。

5. システム コールのカーネル処理

x86 マシンでは、For を区別するために 8 ビットの数値 (0 ~ 255) が使用されます。さまざまな割り込みの場合、この番号は割り込みベクタと呼ばれます。割り込みベクトルの 1 つである 128 (0x80) は、システム コールの実行に特に使用されます。

Linux システムには、IDT と呼ばれる割り込み記述子テーブルと呼ばれるシステム テーブルがあります。 IDT テーブルには 256 のエントリがあり、割り込みベクトルから対応する処理ルーチン (割り込みまたは例外ハンドラー) へのマッピング関係が保存されます。割り込みが発生すると、CPUはIDTテーブルから対応する処理ルーチンのアドレスを見つけて実行します。

システム コール処理ルーチンは、IDT テーブルのエントリを占有します。この項目は、trap_init 関数で次のように初期化されます: set_system_gate(SYSCALL_VECTOR,&system_call);。前述したように、上記のコードの SYSCALL_VECTOR の値は 128 です。

システムコールが発生すると、割り込み機構を通じてシステムコールルーチンsystem_callが呼び出されます。その実行プロセスは大きく 4 つのステップに分かれています:

1. レジスタからシステム コール番号と入力パラメータを取得し、これらのレジスタの値をカーネル スタックにプッシュします。システムコール番号に基づいてシステムコールディスパッチテーブルを検索し、システムコールサービスルーチン(カーネル関数)を見つけます。

2. 見つかったシステムコールサービスルーチンを呼び出します。

3. システムコールサービスルーチンの戻り値をスタックからポップし、再度レジスタに保存します。

上記のシステム コール ルーチン system_call はカーネル空間で実行されます。実行前にシステムコール番号と入力パラメータがレジスタに格納されており、この格納処理はユーザ空間コードによって完了します。実際、最初のセクションで述べたように、実際のシステム コールは基本的にそれをカプセル化するライブラリ関数を持ち、システム コール番号と入力パラメータはこのライブラリ関数に保存されるのが一般的です。システム コール ルーチン system_call が実行されると、戻り値はレジスタを通じてユーザー空間ライブラリ関数に返されます。

以上がシステムコールの目的は何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。