web-dev-qa-db-ja.com

Linuxでは、既存のクラス内でdevice_createをどのように使用しますか?

注:私は今日のようにこの問題をリストしています、私は実装を変更する(移動する)ことに反対していませんたとえば、共通領域へのクラスの作成)それが物事を簡単にする場合...私はそれを行う方法がわかりません。 :End Note

2つのLinuxカーネルモジュールがあり、それらの/ sysエントリを更新しようとしています。グーグルや他のソースを検索して、私は次の行に沿ってたくさんのコードを見てきました:

static dev_t MyDev;
static struct class *c1;

static int __init start_func(void)
{
    ...
    MyDev = MKDEV(nMajor, MINOR_VERSION);
    register_chrdev_region(MyDev, 1, MODULE_NAME);
    c1 = class_create(THIS_MODULE, "chardrv");
    device_create(c1, NULL, MyDev, NULL, MODULE_NAME);
    ....

そして、最初のモジュールでこのコードが機能し、正しく作成されることを確認しました。

/sys/class/chardrv/<MODULE_NAME>

エントリ。私が知りたいのは、既存のクラスでデバイスをどのように作成するかです。つまり、私のモジュールの1つがこの新しいchardrvクラスを作成したので、他のモジュールも同じクラスにデバイスを登録できるようにしたいと思います。

その「chardrv」クラスがすでに存在するため、(2番目のモジュールで)class_create()を再度呼び出すことはできません。

したがって、/ sys/class/chardrvが存在するかどうかを確認するためのチェックを実行できます。これは、class_create()を呼び出す必要があるかどうかを判断するのに役立ちます。これは問題ではありません。明確にするために、ここにいくつかの擬似コードを入れましょう:

if ( path "/sys/class/chardrv" does not exist)
    new_class = class_create("chardrv")
else
    new_class = some how get class "chardrv" handle, or properties, or whatever
device_create(new_class, ...)

したがって、この例のように、クラスがすでに存在し、新しいデバイスをそのクラスに追加したい場合2番目のモジュールからクラス構造を作成し、何らかの方法で正しいデバイスを設定する必要があると想定します「chardrvclass」属性は、以前と同じようにdevice_createを呼び出しますが、その方法がわかりません。

13
Mike

同じクラスでdevice_create関数を使用するには、同じクラスへのポインターを渡すだけです。

クラスを作成したモジュールとは別のモジュールでdevice_createを呼び出したいので、クラスへのポインターのシンボルをエクスポートする必要があります。これを行うには、EXPORT_SYMBOLマクロを使用できます。


例えば:

module1.c

extern struct class *c1;    /* declare as extern */
EXPORT_SYMBOL(c1);          /* use EXPORT_SYMBOL to export c1 */

static dev_t mod1_dev;
static int __init start_func(void)
{
        ...
        /* define class here */
        c1 = class_create(THIS_MODULE, "chardrv");

        /* create first device */
        device_create(c1, NULL, mod1_dev, NULL, "mod1_dev");
        ....
}

module2.c

extern struct class *c1;    /* declare as extern */

static dev_t mod2_dev;
static int __init start_func(void)
{
        ...
        /* c1 is defined in module 1 */

        /* create second device */
        device_create(c1, NULL, mod2_dev, NULL, "mod2_dev");
        ....
}

注:クラス以降、module2の前にmodule1を挿入する必要がありますポインタはmodule1で定義およびエクスポートされます。

それはあなたが期待しているディレクトリを作成するはずです:

  • /sys/class/chardrv/mod1_dev
  • /sys/class/chardrv/mod2_dev

ちなみに、2番目のモジュールをロードしようとしたときにInvalid parametersエラーが発生した場合は、 MakefileにKBUILD_EXTRA_SYMBOLS行を追加 する必要があります。

10
Vilhelm Gray

サンプルコードに従うには、device_create()を再度呼び出して、同じクラスを渡します。例:

MyDev = MKDEV(nMajor, MINOR_VERSION);
register_chrdev_region(MyDev, 1, MODULE_NAME);
c1 = class_create(THIS_MODULE, "chardrv");
device_create(c1, NULL, MyDev, NULL, MODULE_NAME);
...
device_create(c1, NULL, MyDev2, NULL, "mydev2");

クラスが作成されたかどうかを判断するために、パスを確認する必要はありません。コードで作成しているので、c1 == NULLをテストするか、必要に応じてフラグを使用します。

3
mpe

最初のモジュールのモジュール初期化関数でクラスを作成し、-グローバル-クラスシンボルをEXPORT_SYMBOLでエクスポートして、他のモジュールから使用するだけです。

クラスの所有者は最初のモジュールであるため、そのクラスにデバイスを追加するたびに、最初のモジュールの参照カウンターが増加します。誰かが使用している間は、デバイスをアンロードできません。

1