
コンピューティングにおいて、システムコール(syscall )とは、コンピュータプログラムが、そのプログラムが実行されるオペレーティングシステム([ a ])にサービスを要求するプログラム的な方法を指します。これには、ハードウェア関連のサービス(ハードディスクドライブへのアクセスやデバイスのカメラへのアクセスなど)、新しいプロセスの作成と実行、プロセススケジューリングなどの重要なカーネルサービスとの通信などが含まれます。システムコールは、プロセスとオペレーティングシステム間の重要なインターフェースを提供します。
ほとんどのシステムでは、システムコールはユーザー空間プロセスからのみ実行できますが、OS/360や後継システムなど一部のシステムでは、特権システムコードもシステムコールを発行します。[ 1 ]
組み込みシステムの場合、システム コールは通常、 CPU の 特権モードを変更しません。
特権
一部の組み込みシステムを除き、ほとんどの最新プロセッサのアーキテクチャにはセキュリティモデルが採用されています。例えば、リングモデルは、ソフトウェアの実行権限レベルを複数に規定しています。プログラムは通常、自身のアドレス空間に制限されるため、実行中の他のプログラムやオペレーティングシステム自体にアクセスしたり変更したりすることはできません。また、ハードウェアデバイス(フレームバッファやネットワークデバイスなど)を直接操作することも通常はできません。
ただし、多くのアプリケーションはこれらのコンポーネントにアクセスする必要があるため、オペレーティング システムではシステム コールが用意されており、このような操作を明確に定義して安全に実装できます。オペレーティング システムは最高レベルの権限で実行され、アプリケーションがシステム コールを介してサービスを要求できるようにします。システム コールは多くの場合、割り込みによって開始されます。割り込みが発生すると、CPU は自動的に高い権限レベルに移行し、制御がカーネルに渡されます。カーネルは、呼び出し元プログラムに要求されたサービスを許可するかどうかを決定します。サービスが許可されると、カーネルは呼び出し元プログラムが直接制御できない特定の命令セットを実行し、権限レベルを呼び出し元プログラムのレベルに戻し、制御を呼び出し元プログラムに戻します。
仲介者としての図書館
一般的に、システムは通常のプログラムとオペレーティングシステムの中間に位置するライブラリまたはAPIを提供します。 Unix 系システムでは、その API は通常、 glibcなどのC ライブラリ(libc)の実装の一部であり、システムコールのラッパー関数を提供します。ラッパー関数の名前は、呼び出すシステムコールと同じになることがよくあります。Windows NTでは、その API はntdll.dllライブラリのネイティブ APIの一部です。これは、通常のWindows APIの実装で使用される、ドキュメント化されていない API であり、Windows 上の一部のシステムプログラムによって直接使用されます。 ライブラリのラッパー関数は、システムコールを使用するための通常の関数呼び出し規約(アセンブリレベルでのサブルーチン呼び出し) を公開するとともに、システムコールをよりモジュール化します。 ここで、ラッパーの主な機能は、システムコールに渡すすべての引数を適切なプロセッサレジスタ(およびおそらくコールスタック) に配置し、カーネルが呼び出す一意のシステムコール番号を設定することです。 このように、OS とアプリケーションの間に存在するライブラリは、移植性を高めます。
ライブラリ関数の呼び出し自体はカーネルモードへの切り替えを引き起こさず、通常は通常のサブルーチン呼び出しです(たとえば、一部の命令セットアーキテクチャ(ISA)では「CALL」アセンブリ命令を使用します)。実際のシステムコールはカーネルに制御を移します(そして、それを抽象化するライブラリ呼び出しよりも実装依存およびプラットフォーム依存です)。たとえば、Unix系システムでは、forkおよびexecveはCライブラリ関数であり、順に、forkおよびシステムコールを呼び出す命令を実行します。アプリケーションコードexecで直接システムコールを行うのはより複雑で、埋め込みアセンブリコードの使用が必要になる場合があります(CおよびC++)。また、システムコール操作の低レベルバイナリインターフェースの知識も必要になりますが、これは時間の経過とともに変更される可能性があり、したがってアプリケーションバイナリインターフェースの一部ではない場合があります。ライブラリ関数はこれを抽象化するためのものです。
エクソカーネルベースのシステムでは、ライブラリは仲介役として特に重要です。エクソカーネルでは、ライブラリはユーザーアプリケーションを非常に低レベルのカーネルAPIから保護し、抽象化とリソース管理を提供します。
IBMのOS/360、DOS/360、TSS/360は、アセンブリ言語マクロのライブラリを通じてほとんどのシステムコールを実装していますが、[ b ]呼び出しリンケージを持つサービスもいくつかあります。これは、アセンブリ言語でのプログラミングが高級言語の使用よりも一般的だった時代に始まったことを反映しています。したがって、IBMのシステムコールは高級言語プログラムでは直接実行できず、呼び出し可能なアセンブリ言語ラッパーサブルーチンが必要でした。それ以来、IBMは、z/OSやz/VSEなどの高級言語から呼び出すことができる多くのサービスを追加しました。最近のMVS/SPのリリースとそれ以降のすべてのMVSバージョンでは、一部のシステムコールマクロがプログラム呼び出し(PC)を生成します。
例とツール
Unix、Unix系、その他のPOSIX準拠オペレーティングシステムでは、よく使われるシステムコールはopen、、、、、、、、、、、、です。多くの現代のオペレーティングシステムにはread、数百ものシステムコールがあります。例えば、LinuxとOpenBSDはそれぞれ300種類以上のシステムコールがあり、[ 2 ] [ 3 ]、 NetBSDは約500種類、[ 4 ] 、 FreeBSDは500種類以上、[ 5 ]、 Windowsは約2000種類で、win32k(グラフィカル)とntdll(コア)のシステムコールに分かれています[ 6 ]。一方、Plan 9は54種類です[ 7 ]。writeclosewaitexecforkexitkill
strace、ftrace 、 trussなどのツールを使用すると、プロセスを起動から実行し、そのプロセスが呼び出すすべてのシステムコールを報告したり、既に実行中のプロセスにアタッチして、そのプロセスがユーザーの権限を侵害しない限り、そのプロセスが行うすべてのシステムコールを傍受したりできます。プログラムのこの特別な機能は、通常、ptraceなどのシステムコールや、 procfs内のファイルに対するシステムコールによっても実装されます。
典型的な実装
システムコールを実装するには、ユーザー空間からカーネル空間への制御の移行が必要であり、これには何らかのアーキテクチャ固有の機能が関係します。これを実装する一般的な方法は、ソフトウェア割り込みまたはトラップを使用することです。割り込みはオペレーティングシステムのカーネルに制御を移行するため、ソフトウェアは必要なシステムコール番号をレジスタに設定し、ソフトウェア割り込みを実行するだけで済みます。
これは多くのRISCプロセッサに提供されている唯一の技術ですが、 x86などのCISCアーキテクチャは追加の技術をサポートしています。例えば、x86命令セットには/命令と/命令が含まれています(これら2つのメカニズムはそれぞれAMDとIntelによって独立して開発されましたが、本質的には同じ機能を果たします)。これらは「高速」な制御転送命令であり、割り込みのオーバーヘッドなしにシステムコールの制御をカーネルに迅速に移すように設計されています。[ 8 ] Linux 2.5では、利用可能な場合はx86でこの命令を使用しました。それ以前は、割り込み0x80が実行される前にシステムコール番号をレジスタに格納する命令を使用していました。[ 9 ] [ 10 ]SYSCALLSYSRETSYSENTERSYSEXITINTEAX
古いメカニズムとしてコールゲートがあります。これは元々 Multicsで使用され、後にIntel x86のコールゲートの例を参照のこと。これは、オペレーティングシステムが事前に設定しておく安全な制御転送メカニズムを使用して、プログラムがカーネル関数を直接呼び出すことを可能にします。このアプローチはx86では普及していません。これはおそらく、x86のメモリセグメンテーションを使用するfar call(現在のコードセグメントとは異なるセグメントにあるプロシージャへの呼び出し[ 11 ])が必要であり、それがもたらす移植性の欠如、そして前述のより高速な命令の存在が原因であると考えられます。
IA-64アーキテクチャでは、 EPC(Enter Privileged Code)命令が使用されます。最初の8つのシステムコール引数はレジスタに渡され、残りはスタックに渡されます。
IBM System/360メインフレーム・ファミリーおよびその後継機種では、レジスタではなく命令に番号を記述するスーパーバイザー呼び出し命令( SVC )によって、 IBM独自のオペレーティングシステムのほとんどにおける従来の機能と、Linux におけるすべてのシステムコールが実装されています。MVS の後継バージョンでは、多くの新しい機能に対してプログラム呼び出し命令 (PC) が使用されています。特に、PC は呼び出し元がサービス要求ブロック(SRB) モードにある可能性がある場合に使用されます。
PDP -11ミニコンピュータはEMT、TRAP、IOT命令を採用していました。これらの命令はIBM System/360 SVCやx86 INT命令と同様に、命令内にコードを配置し、特定のアドレスへの割り込みを生成してオペレーティングシステムに制御を移します。PDP -11シリーズの後継機種であるVAX 32ビットでは、CHMK、CHME、CHMS命令を用いて、様々なレベルの特権コードへのシステムコールを実行しました。コードは命令の引数として使用されます。
システムコールのカテゴリ
システムコールは、おおよそ6つの主要なカテゴリに分類できます。[ 12 ]
- プロセス制御
- ファイル管理
- ファイルの作成、ファイルの削除
- 開く、閉じる
- 読む、書く、再配置する
- ファイル属性の取得/設定
- デバイス管理
- デバイスの要求、デバイスの解放
- 読む、書く、再配置する
- デバイス属性の取得/設定
- デバイスを論理的に接続または切断する
- 情報メンテナンス
- システム全体の情報を取得/設定します (時間、日付、コンピューター名、エンタープライズなどを含む)
- プロセス、ファイル、またはデバイスのメタデータを取得/設定します (作成者、オープン元、作成日時などを含む)
- コミュニケーション
- 通信接続の作成、削除
- メッセージを送信、受信する
- 転送ステータス情報
- リモートデバイスの接続または切断
- 保護
- ファイルの権限を取得/設定する
プロセッサモードとコンテキストスイッチング
ほとんどのUnix系システムでは、システムコールはカーネルモードで処理されます。これはプロセッサ実行モードをより特権的なものに変更することで実現されますが、プロセスのコンテキストスイッチは必要ありません(ただし、特権コンテキストスイッチは発生します)。ハードウェアはプロセッサステータスレジスタに基づいて実行モードの観点から世界を認識し、プロセスはオペレーティングシステムによって提供される抽象化です。システムコールは通常、別のプロセスへのコンテキストスイッチを必要とせず、代わりに、それを呼び出したプロセスのコンテキストで処理されます。[ 13 ] [ 14 ]
マルチスレッドプロセスでは、複数のスレッドからシステムコールが実行されることがあります。このようなシステムコールの処理方法は、特定のオペレーティングシステムカーネルとアプリケーション実行環境の設計に依存します。以下のリストは、オペレーティングシステムが採用している典型的なモデルを示しています。[ 15 ] [ 16 ]
- 多対一モデル:プロセス内の任意のユーザースレッドからのすべてのシステムコールは、単一のカーネルレベルスレッドによって処理されます。このモデルには重大な欠点があります。ブロッキングシステムコール(ユーザーからの入力待ちなど)は、他のすべてのスレッドをフリーズさせる可能性があります。また、一度に1つのスレッドしかカーネルにアクセスできないため、このモデルでは複数のプロセッサコアを活用できません。
- 1対1モデル:システムコール中、各ユーザースレッドはそれぞれ異なるカーネルレベルのスレッドにアタッチされます。このモデルは、システムコールをブロックするという前述の問題を解決します。このモデルは、主要なLinuxディストリビューション、macOS、iOS、最近のWindowsおよびSolarisバージョンで採用されています。
- 多対多モデル:このモデルでは、ユーザースレッドのプールがカーネルスレッドのプールにマッピングされます。ユーザースレッドプールからのすべてのシステムコールは、対応するカーネルスレッドプール内のスレッドによって処理されます。
- ハイブリッドモデル:このモデルは、カーネルの選択に応じて、多対多モデルと1対1モデルの両方を実装します。これは、IRIX、HP-UX、Solarisの古いバージョンで見られます。
参照
注記
参考文献
- ^「SVCルーチンの作成」IBM System/360オペレーティング・システム・プログラマーズ・ガイド(PDF)。第3版。IBM。1967年3月。32 ~ 36ページ。C28-6550-2。
- ^ "syscalls(2) - Linuxマニュアルページ" .
- ^ OpenBSD (2013年9月14日). 「システムコール名 (kern/syscalls.c)」 . BSD相互参照.
- ^ NetBSD (2013年10月17日). 「システムコール名 (kern/syscalls.c)」 . BSD相互参照.
- ^ 「FreeBSD syscalls.c、システムコール名と ID のリスト」。
- ^マテウシュ「j00ru」ユルチク (2017 年 11 月 5 日)。「Windows WIN32K.SYS システム コール テーブル (NT/2000/XP/2003/Vista/2008/7/8/10)」。
{{cite web}}: CS1 maint: numeric names: authors list (link) - ^ "sys.h" . Plan 9 from Bell Labs . 2023年9月8日時点のオリジナルよりアーカイブ。システムコール名と ID のリスト。
- ^ "SYSENTER" . OSDev wiki . 2023年11月8日時点のオリジナルよりアーカイブ。
- ^ Anonymous (2002年12月19日). 「Linux 2.5でvsyscallsとsysenterのサポートが開始」 . KernelTrap . 2008年1月1日閲覧。
- ^ Manu Garg (2006). 「Linux 2.6におけるSysenterベースのシステムコールメカニズム」 .
- ^ 「Liberation: x86命令セットリファレンス」renejeschke.de . 2015年7月4日閲覧。
- ^ Silberschatz, Abraham (2018). 『オペレーティングシステムの概念』 ピーター・B・ガルビン、グレッグ・ガニエ(第10版) ホーボーケン、ニュージャージー州: Wiley 67頁ISBN 9781119320913. OCLC 1004849022 .
- ^ Bach, Maurice J. (1986)、「UNIXオペレーティングシステムの設計」、Prentice Hall、pp.15-16。
- ^ Elliot, John (2011年10月1日). 「ProgClubにおけるシステムコール実装に関する議論(Bach 1986からの引用を含む)」 . 2012年7月24日時点のオリジナルよりアーカイブ。 2011年10月1日閲覧。
- ^ 「スレッド」。
- ^ 「スレッド モデル」(PDF)。
さらに読む
- 「Linuxシステムコールを使用したカーネルコマンド」 IBM developerWorks 2010年2月10日。2017年2月11日時点のオリジナルよりアーカイブ。
- Choudhary, Amit; Linux 2.6 でシステムコールを実装するための HOWTO
- Jorrit N. Herder、Herbert Bos、Ben Gras、Philip Homburg、Andrew S. Tanenbaum、「Minix 3 におけるモジュラーシステムプログラミング」、;login: 31、第2号(2006年4月)、19–28、2018年3月5日アクセス
- Gulbrandsen, John; SYSENTER命令によるシステムコールの最適化、CodeGuru.com、2004年10月8日
外部リンク
- 現代のUnix系システムコールのリスト
- Linux/i86 でのシステムコールの仕組み(1996、1993 0.99.2 カーネルに基づく)
- Linux 2.6 (2006)における Sysenter ベースのシステムコールメカニズム
- C言語で書かれたシンプルなオープンUnixシェル - Unixのシステムコールの例
- osdev ウィキ