web-dev-qa-db-ja.com

ユーザー空間とカーネルの通信に/ devと/ sysを使用する場合

私はLinuxドライバー開発を始めたばかりで、概念的な質問があります。これは、他の新参者もカーネル開発に役立つと思います。

Linux Device Driversの本を読んでいて、Ch。本の3。これまで、/devフォルダー内のファイルにopencloseなどのコマンドを発行することにより、ユーザースペースがカーネル機能にアクセスできることを確認しました。

制御を共有するもう1つの方法は、/sysのファイルを使用する方法です。この場合、sysファイルの読み取りまたは書き込みは、ドライバーと通信できます。

各メソッドのユースケースは何ですか?それらは同じタスクへの2つのアプローチですか? 1つは別の制限がありますか?誰かが一方が他方よりも役立つかもしれない実用的な例を誰かが共有できますか?

ここで他の質問を読んだところ、devsysについて説明されました。これは役に立ちますが、両方の違いと使用方法について、もう少し詳しく知りたいと思っていました。

5
animal07

大まかに:

/devには、以前のUnixシステムではカーネルと対話する唯一の方法であったデバイスノードが含まれています。 blockデバイスとcharacterデバイスの2つのタイプがあります。対応するAPIは、ブロックベースのI/O(ある種のディスク)または文字ベースのI/O(たとえば、シリアルポート)を可能にするものに適合しています。

/sys(および/proc)は後に追加されました。おそらく Plan 9 OSに触発されました。それらは完全なディレクトリサブツリーを提供し、これらのサブツリーのファイルエントリには、読み取り時、または書き込み時に内部状態を設定するときのカーネルモジュールの内部状態を説明するテキストが含まれています。

したがって、一般的なアプリケーションは次のようになります。

ある種のストレージデバイス用のカーネルドライバーを書きたいですか?使う /devノードはデバイス自体にアクセスし、/sys(または/proc)エントリを使用して、ストレージへのアクセス方法を微調整します。

7
dirkt

/sysの対象範囲は、第14章「Linuxデバイスモデル」にあります。それは一緒に遊ぶためのいくつかのサンプルコードを提供します。しかし、この本はよりコード駆動型のアプローチであり、設計原則がどのように見えるかを尋ねるのに役立つと思います。

ユーザー空間とカーネルの通信に/ devと/ sysを使用する場合

最初の答えは、あなた自身を選ばないということです。あるタイプのデバイス用のドライバーを作成するとき、カーネルにはすでに同じタイプのデバイスの多くの例があります。既存のデバイスと同等のコードパターンを使用します。 (最新のドキュメントはコード自体です。多くのカーネルインターフェイスには完全なドキュメントや最新のドキュメントがありません。申し訳ありません!)

これが、デバイスドライバーを作成する主な理由です。さまざまなデバイスごとにさまざまな詳細をコーディングする必要なく、プログラムが使用できる一貫したインターフェースを提供しています。

これは、より一般的なアドバイスを無効にします。 Linuxのサブシステム(デバイスのタイプなど)が「間違っている」ように見える方法を使用しているが、一貫してそうしている場合は、そのサブシステムのドライバーを作成するときにも一貫していて「間違っている」必要があります。

/ dev

データパスには/ dev /を使用する必要があります。本の別のセクションで説明されているネットワークデバイスを除きます。

/ dev /特殊ファイルは、標準化されたUNIX操作に使用する必要があります:read()write()poll()/select()mmap()ioctl() sがunixまたはlinuxで効果的に標準化されている場合も望ましいです。これらのいくつかのシステムコール(およびいくつかの派生バリアント)は、ほとんどすべての場合に使用されます。それらに慣れ始めてください:)。 ioctl()は、ここでエスケープハッチです。これを使用して、ドライバーに他の操作をいくつでも定義させることができます。

/ sys

sysfs書き込みは、構成パラメーターのために、はるかに少ないケースで使用する必要があります。それらはプレーンテキスト形式である必要があり、単一の値のみが含まれている必要があります。[*]異なるsysfsファイルが多すぎないようにする必要があります。あなたはそれらの限界を素早く見始めることができます。

また、sysfsファイルは基本的に変数を読み取る必要があると言うこともできます(変数は書き込み可能であってもなくてもかまいません)。それらを読んでハードウェアが動作することはないと思います。あなたはすでにこれらの線に沿って考えていたと思います。

Sysfsファイルの利点は、実験に非常に便利なことです。シェルコマンドを使用して、それらの一覧表示、読み取り、書き込みを簡単に行うことができます。これも危険です。実験的な状態でsysfsファイルを公開しないように注意する必要があります。他の人があなたのsysfsファイルに依存し始めると、ユーザーのスクリプトを壊すような方法で何かを変更したい場合、カーネルのメンテナは非常に不幸になります。

Sysfs(ディレクトリ階層とシンボリックリンク)をトラバースすることも、デバイスがどのように編成されているかを確認するのに役立ちます。

また、sysfsの変更を概念的に監視することは、プログラムが新しいデバイスを検出する方法です(たとえば、プラグインされたとき)。技術的には、これらのイベントはファイルシステム自体を通じて配信されませんが、各イベントは特定のsysfsディレクトリを指します。

Udevデーモンはこれらのイベントを待機します。通常のプログラムは、必要に応じてudev/libudevに依存する傾向があります。たとえば、udevルールは、イベントの受信時にsysfsディレクトリ内のいくつかのファイルを読み書きする場合があります。新しく検出されたデバイスの設定を変更します。

例を見る

既存の例を見ることは非常に良い考えです。おそらく1つの例だけを見てはならず、それが他の場所でも同じように機能すると仮定します。

Dirktが言うように、/dev/sdaのようなブロックストレージデバイスへのアクセスは、/devの非常に標準化された使用法です。最大物理IO /sys/class/block/sda/で公開されているサイズなどのいくつかのパラメータ-queueサブディレクトリを確認してください。

多くのsysfsファイルは、カーネルツリーDocumentation/ABI/*/sysfs-*に文書化されています。例: https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-block

「キャラクターデバイス」はあまり具体的ではないことに注意してください。基本的に、ブロックデバイスでもネットワークデバイスでもないデバイスに使用されます:-)。まったく新しいクラスのデバイスを実装する必要がある場合は、まったく新しいタイプのキャラクターデバイスを定義し、ioctl()操作の新しいセットを定義するという恐ろしい仕事をしなければならないでしょう。

自分のシステムで定義されている他のいくつかのタイプのデバイスを確認するために、/sys/class/を調べ始める場合があります。

/sys/には、/dev/デバイスのリストも含まれますが、名前ではなくデバイス番号でリストされます。 ls -l /sys/dev/char/およびls -l /sys/dev/block/を参照してください。これは、udev/devを管理する方法を説明するのに役立ちます。/devに表示されるすべてのデバイスは、/sysのオブジェクトとしてリストされます。[**]


[*] sysfs ueventファイルには複数の値が含まれており、実際にはコア機能です。ただし、ueventファイルを使用して内部の値を変更することはできません。つまり、これは単にueventを見て、私のアドバイスが間違っているとは考えないでください。このようなファイルを自分で定義しないでください。デバイスドライバーはueventファイルに行を追加できます。 Ithink良い例は、udevルールでテストしたい非常に便利な識別プロパティがある場合です。

[**] /dev/pts/0は実際には別のファイルシステム「devpts」によって実装されるため、/sysなどは/dev/pts/0にリストされていません。非常に特殊なケースとして、/dev/pts/0を無視してください。私がこれを結論付けた答えはありますが、私が言ったことに何かを追加することは本当にないと思います。それはここにあります: 端末を開いたときにTTYは常に使用されますか?

3
sourcejedi