コンピューティングにおいて、 ( input/output controlioctlの略) は、デバイス固有の入出力操作や、通常のファイル読み書き/シーク操作では表現できないその他の操作を行うためのシステムコールです。要求コードを指定するパラメータを受け取ります。呼び出しの効果は、要求コードに完全に依存します。要求コードは多くの場合、デバイス固有です。たとえば、物理デバイスにディスクの排出を指示できるCD-ROMデバイスドライバは、排出を実行するための要求コードを提供します。デバイス非依存の要求コードは、コアシステムソフトウェアのみが使用する、またはまだ開発中のカーネル関数にユーザー空間からアクセスできるようにするために使用されることがあります。ioctl
このシステムコールは、 Unixバージョン 7でioctl初めてその名前で登場しました。LinuxやmacOSを含むほとんどのUnixおよびUnix ライクなシステムでサポートされていますが、使用可能なリクエストコードはシステムによって異なります。Microsoft Windows は、 Win32 APIで「 」という名前の同様の機能を提供しています。DeviceIoControl
従来のオペレーティングシステムは、ユーザー空間とカーネルの2つの層に分けられます。テキストエディタなどのアプリケーションコードはユーザー空間に存在し、ネットワークスタックなどのオペレーティングシステムの基盤となる機能はカーネルに存在します。カーネルコードは機密性の高いリソースを扱い、アプリケーション間のセキュリティと信頼性の障壁を実装します。そのため、ユーザーモードのアプリケーションは、オペレーティングシステムによってカーネルリソースへの直接アクセスを制限されています。
ユーザー空間アプリケーションは通常、カーネル層に存在するシステムコールを介してカーネルに要求を行います。システムコールは通常、「システムコールベクター」と呼ばれる形式をとり、目的のシステムコールはインデックス番号で示されます。例えば、exit()はシステムコール番号1、 はwrite()番号4といった具合です。システムコールベクターは、要求に応じたカーネル関数を見つけるために使用されます。このようにして、従来のオペレーティングシステムは通常、ユーザー空間に対して数百ものシステムコールを提供しています。
システムコールは標準的なカーネル機能にアクセスするための便利な設計ではありますが、非標準のハードウェア周辺機器にアクセスするには不適切な場合があります。必然的に、ほとんどのハードウェア周辺機器(デバイスとも呼ばれます)はカーネル内からのみ直接アクセス可能です。しかし、ユーザーコードはデバイスと直接通信する必要がある場合があります。たとえば、管理者はイーサネットインターフェイスのメディアタイプを設定する場合があります。最新のオペレーティングシステムは多様なデバイスをサポートしており、その多くは豊富な機能を提供しています。これらの機能の中にはカーネル設計者が想定していないものもあり、その結果、カーネルがデバイスを使用するためのシステムコールを提供することは困難です。
この問題を解決するために、カーネルは拡張可能な設計となっており、カーネル空間で実行され、デバイスに直接アクセスできるデバイスドライバioctlと呼ばれる追加モジュールを受け入れることができます。インターフェースとは、ユーザー空間がデバイスドライバと通信するための単一のシステムコールです。デバイスドライバへの要求はioctl、通常、デバイスへのハンドルと要求番号によって、このシステムコールに基づいてベクタリングされます。このように、基本的なカーネルは、デバイスがサポートする機能について何も知らなくても、また、管理しきれないほど多くのシステムコールを必要とせずに、ユーザー空間がデバイスドライバにアクセスできるようにします。
の一般的な用途の一つは、ioctlハードウェアデバイスの制御です。
例えば、Win32システムでは、これらの関数呼び出しによってUSBioctlデバイスと通信したり、接続されているストレージデバイスのドライブジオメトリ情報を取得したりすることができます。
OpenBSDおよびNetBSDでは、擬似デバイスドライバとユーティリティioctlによって使用され、 RAIDボリューム管理を、に似た統一されたベンダー非依存のインターフェースで実装します。[ 1 ] [ 2 ]bio(4)bioctlifconfig
エンドユーザーアプリケーションに公開されるコードにおける使用例の1つはioctl、端末入出力です。
Unixオペレーティングシステムは、従来からコマンドラインインターフェイスを多用しており、当初はシリアルポートに接続されたVT100などのハードウェアテキスト端末、その後は擬似端末を使用した端末エミュレータやリモートログインサーバーが使われてきました。シリアルポートデバイスと擬似端末はどちらも呼び出しを使用して制御および設定されます。たとえば、ディスプレイサイズは呼び出しを使用して設定されます。TIOCSTI (端末入出力制御、端末入力のシミュレート) ioctl 関数は、デバイスストリームに文字をプッシュできます。[ 4 ]ioctlTIOCSWINSZ
アプリケーションがカーネルを拡張する必要がある場合(例えば、ネットワーク処理を高速化するため)、コールはユーザー空間コードとカーネル拡張機能ioctlをつなぐ便利な手段となります。カーネル拡張機能は、名前で開くことができるファイルシステム上の場所を提供し、そこから任意の数のコールをディスパッチできるため、オペレーティングシステムにシステムコールを追加することなく拡張機能をプログラムできます。ioctl
OpenBSDの開発者 によると、ioctlと はカーネルを拡張するためのsysctl2つのシステムコールsysctlであり、おそらく の方がよりシンプルである。[ 5 ]
NetBSDでは、ハードウェア監視sysmon_envsysのフレームワークはを介して使用されますが、OpenBSDとDragonFly BSDでは、対応するフレームワークにが使用されます。NetBSD の の最初の改訂版は、 が利用可能になる前に で実装され、フレームワークは実験的であり、インターフェースが開発された場合はそれに置き換えるべきであるというメッセージがありました。 [ 6 ] [ 7 ]これは、2003 年に が導入された OpenBSD で が選択された理由を説明する可能性があります。しかし、2007 年に の頃にフレームワークが再設計されたとき、システムコールは のままで、メッセージは削除されました。[ 8 ]ioctlproplibsysctlhw.sensorsenvsysioctlproplibsysctl(8)sysctlhw.sensorsenvsysproplibioctl
このioctlシステムコールは、 Unix バージョン 7で初めて登場し、 stty[ 9 ]およびシステムコールの代替としてgtty、追加のリクエストコード引数とともに使用されました。この呼び出しは、次のパラメータをioctl受け取ります。
カーネルは通常、ioctl要求番号とデータを必要に応じて解釈できるデバイスドライバに直接呼び出しをディスパッチします。各ドライバの開発者は、そのドライバ固有の要求番号を文書化し、ヘッダーファイルに定数として提供します。
リクエスト番号は通常、リクエストの対象となるデバイスまたはデバイスクラスを識別するコードと、特定のリクエストを示す番号を組み合わせたものです。デバイスまたはデバイスクラスを識別するコードは通常、単一のASCII文字です。4.2BSD以降のBSDリリース、それらのリリースから派生したオペレーティングシステム、およびLinuxを含む一部のUnixシステムでは、リクエスト番号内にデバイスドライバとの間で転送されるデータのサイズとデータ転送の方向もエンコードする規則があります。このような規則が遵守されているかどうかに関わらず、カーネルとドライバは連携して、認識できないドライバにリクエストを行ったアプリケーションに、統一されたエラーコード(シンボル定数で表される)を配信します。ENOTTY
この記憶術(従来は「タイプライターではありませんENOTTY」というテキストメッセージに関連付けられていた)は、通話機能を組み込んだ初期のシステムに由来しており、当時はこのエラーメッセージはテレタイプ端末のみで発生していました。記号による記憶術は互換性要件によって固定されていますが、現代のシステムの中には、「不適切な端末制御操作です」(またはそのローカライズ版)といった、より一般的なメッセージを表示するものもあります。ioctltty
TCSETSこれはシリアルポートioctlでの呼び出しの一例です。シリアルポートでの通常の読み取りおよび書き込み呼び出しは、データバイトの受信と送信を行います。このような通常の入出力とは別の呼び出しは、特殊文字の処理やポートの出力信号(DTR信号など)といった、さまざまなドライバオプションを制御します。ioctl(fd,TCSETS,data)
Win32 はDeviceIoControl、以下のものをパラメータとして受け取ります。
OVERLAPPEDが使用されている場合の構造。Win32デバイス制御コードは、実行される操作のモードを考慮に入れます。
デバイスドライバのセキュリティに影響を与える、定義された動作モードは4つあります。
METHOD_IN_DIRECT: バッファアドレスがユーザーモード呼び出し元によって読み取り可能であることが検証されます。METHOD_OUT_DIRECT: バッファアドレスがユーザーモード呼び出し元によって書き込み可能であることが検証されます。METHOD_NEITHERユーザーモードの仮想アドレスは、マッピングや検証なしにドライバに渡されます。METHOD_BUFFERED: IOマネージャが制御する共有バッファは、ユーザーモードとの間でデータを転送するために使用されます。デバイスやカーネル拡張機能は、追加の新しいシステムコールを使用してユーザー空間にリンクされる場合があるが、オペレーティングシステムの開発者はシステムコールのインターフェースを簡潔かつ効率的に保とうとするため、この方法はめったに採用されない。
Unix系オペレーティングシステムでは、他にも2つのベクタ呼び出しインターフェースがよく使われています。1つはfcntl「ファイル制御」システムコールで、開いているファイルを設定し、ノンブロッキングI/Oを有効にするなどの状況で使用されます。もう1つはsetsockopt「ソケットオプション設定」システムコールで、開いているネットワークソケットを設定し、BSDipfw Unixシステムでパケットファイアウォールを設定する際に使用されます。
ioctlが、メモリマッピングシステムコールを使用して、自身のアドレス空間の一部をカーネルのアドレス空間に紐付けます。このインターフェースは、デバイスとユーザー空間アプリケーション間で大量のデータを転送するはるかに効率的な方法です。個別のシステムコールioctlや読み書きシステムコールでは、ユーザー空間からカーネルへの遷移が繰り返されるためオーバーヘッドが発生しますが、メモリマップドされたアドレス範囲へのアクセスではそのようなオーバーヘッドは発生しません。DeviceIoControl METHOD_アクセスで十分です。Netlink は、プロセス間通信(IPC)のためのソケットのようなメカニズムであり、より柔軟な後継となるように設計されていますioctl。
ioctlioctl コールは、カーネルのシステムコールインターフェースの複雑さを最小限に抑えます。しかし、開発者がカーネルプログラミングインターフェースの断片を「保管」できる場所を提供することで、ioctlユーザーとカーネル間の API 全体が複雑化します。数百のシステムコールを提供するカーネルは、数千の ioctl コールを提供する可能性があります。
呼び出しのインターフェースはioctl従来のシステムコールとは多少異なるように見えるが、実際には呼び出しioctlとシステムコールの間に大きな違いはない。ioctl呼び出しは単にディスパッチメカニズムが異なるシステムコールに過ぎない。したがって、カーネルのシステムコールインターフェースの拡張に反対する多くの議論は、ioctlインターフェースにも適用できる。
アプリケーション開発者にとって、システムコールはアプリケーションのサブルーチンと何ら変わりなく見えます。単に引数を取り、値を返す関数呼び出しに過ぎません。コアライブラリ(例libc:)は、システムコールの呼び出しに伴う複雑さを隠蔽します。これはioctl、ドライバインターフェースが通常ユーザー空間ライブラリとともに提供される場合にも当てはまります(例:グラフィックスドライバのダイレクトレンダリングインフラストラクチャ用のMesa)。
Libpcapとlibdnetはioctl、それぞれパケットキャプチャとパケットI/Oのためのインターフェースの複雑さを隠蔽するように設計された、サードパーティ製のラッパーUnixライブラリの2つの例です。
従来の設計では、カーネルはリング0に配置され、リング1のデバイスドライバやマイクロカーネルとは分離されていました。しかし、システムコールがカーネル/ユーザー空間インターフェースに課すのと同様のリング間の遷移オーバーヘッドがドライバ/カーネルインターフェースにも加わるため、この方式はほぼ放棄されました。その結果、現在ではリング0にも配置されるようになったすべてのドライバが、カーネルコアと同等のセキュリティレベルを維持する必要があるという、実際には困難な要件が生じました。
主流のオペレーティングシステムのユーザーとカーネルのインターフェースは、リリース前にコードの欠陥やセキュリティの脆弱性について徹底的に監査されることが多いが、これらの監査は通常、十分に文書化されたシステムコールインターフェースに焦点を当てている。たとえば、監査担当者は、ユーザーIDの変更などの機密性の高いセキュリティコールが管理者ユーザーのみに利用可能であることを確認するかもしれない。コール のハンドラもリング0に直接存在するため、ユーザースペースioctlからの入力も同様に慎重に検証する必要がある。デバイスドライバの脆弱性は、たとえば無効なバッファをコールに渡すことによって、ローカルユーザーによって悪用される可能性がある。 実際には、これは当てはまらない。インターフェースは、システムコールよりも大きく、多様で、定義が不十分なため、監査が困難である。さらに、コールはサードパーティの開発者によって提供されることが多く、多くの場合、コアオペレーティングシステムがリリースされた後であるため、コールの実装は一般的に精査が少なく、より多くの脆弱性を抱えている可能性がある。最後に、特にサードパーティのデバイスドライバの場合、一部のコールは完全に文書化されていない可能性がある。ioctlioctlioctlioctlioctl
これに対するさまざまな修正が作成されており、得られた速度を維持しながら、以前のセキュリティと同等のセキュリティを実現することを目標としています。Win32およびUnixオペレーティングシステムは、デバイスに特定のアクセス制御を適用することで、アプリケーションによるユーザー空間デバイス名へのアクセスを保護できます。デバイスドライバ開発者がユーザー空間でアクセス可能なオブジェクトに適切なアクセス制御を適用しない場合、セキュリティ上の問題が発生する可能性があります。一部の最新のオペレーティングシステムは、システムコールラッパーを使用して、カーネルを悪意のあるユーザー空間コード (バッファオーバーフロー攻撃 に感染したアプリケーションなど)から保護します。システムコールラッパーは、どのシステムコールをどのアプリケーションが呼び出せるかを指定することで、ロールベースのアクセス制御を実装します。たとえば、ラッパーを使用して、メールプログラムが他のプログラムを起動する権利を「取り消す」ことができます。インターフェースは、システムコールラッパーの数が多く、それぞれが異なる引数を取るため、システムコールラッパーを複雑にします。これらの引数の中には、通常のプログラムで必要とされるものもあります。さらに、このようなソリューションは、得られたオーバーヘッドの削減効果を打ち消します。ioctl
{{cite web}}: CS1 maint: 数値名: 著者リスト (リンク)/dev/sysmon 経由で利用可能な ioctl(2) インターフェース。
[...] TIOCSTI [...]は「端末I/O制御、端末入力のシミュレート」の略です。この機能を実装しているシステムでは、デバイスストリームに1文字がプッシュされ、次にプロセスがそのデバイスから読み取るときに、そこにプッシュされた文字が取得されます。
カーネルに機能を追加するために使用できるシステムコールは 2 つあります (別のシステムコールを追加せずに)。ioctl(2) と sysctl(3) です。後者は、新しい機能を実装するのが非常に簡単だったため選択されました。
この API は実験的なものであり、いつでも非推奨になる可能性があります... この API 全体は、sysctl(8) インターフェースまたはカーネル イベント メカニズムが開発された場合、それに置き換えられる必要があります。