カーネルプラットフォームドライバでユーザ空間イベントを生成する

カーネルプラットフォームドライバでユーザ空間イベントを生成する

コンテキスト

プラットフォームドライバオンチップコンポーネントおよびその他の検索不能デバイス用に作成されたデバイスドライバ。このような場合に私が集中しているのはSNVS電源オン/オフドライバi.MX6ベースのプラットフォームに適用可能です。

質問

私は、プラットフォームのオン/オフボタンが切り替えられたときにユーザースペースプログラムが情報を取得できるようにしたいと思います。私は2つの可能なアプローチを識別し、少なくとも1つを削除しました。

  1. 登録するキャラクターデバイスドライバと同じ割り込みを共有するカーネルモジュールです。ユーザーモードプログラムが非常にクエリしてioctl動作read/writeすることを許可します。不可能:IRQが共有されていません
  2. デバイスを管理するときは、ueventsカーネルから公開された情報を聞き、次のものを使用してください。udev ルールドライバーをマッチングして対処してください。残念ながらuevent、ボタンを押しても情報は公開されません。これは、単にueventデバイスをロードまたはアンロードするときに情報を出力することが目的であるためです。プラットフォームデバイスとして、デバイスは起動時にすぐにロードされ、アンロードされません。私のカーネル構成者によると、まったく削除できません(カーネルの一部である必要があります)。

ソリューション1

割り込みでボタンを押すたびにイベントが発生したいので、snvs_pwrkey.cドライバを直接生成するように修正しましたueventこの投稿出発点へ。ドライバを次のように変更しました。

...

static irqreturn_t imx_snvs_pwrkey_interrupt (int irq, void *dev_id)
{
    ...

    struct platform_device *pdev = dev_id;
    int err = 0;

    ...

    /* Sysfs notify: I chose "change" as the event type */
    err = kobject_uevent(&(pdev->dev.kobj), KOBJ_CHANGE);
    pr_err("%s :: kobject_uevent = %d\n", __FUNCTION__, err);

    return IRQ_HANDLED
}

...

次に、次のudevルールを使用してそれをキャプチャします。

# /etc/udev/rules.d/90-local.rules

KERNEL="20cc000.snvs:snvs-powerkey", SUBSYSTEM=="platform", DRIVER=="snvs_pwrkey", ACTION=="change", RUN+="/sbin/poweroff"

これは実際に働く、STDOUTが実行されると、例外とスタックトレースが発生します(ただし、最初の呼び出しでのみ)。これは、性能や安定性に顕著な影響を及ぼさなくても明らかに望ましくない。しかし、もっと重要なのは、ueventユーザースペースに割り込み通知を送信するためにsysfsがデバイスを管理するために使用されるシステムをハイジャックしているため、これが乱用だと思うことです。

もしそうなら、私が達成したい目標を達成するためのより良い方法があるかどうか疑問に思います。モジュールと割り込みを共有できないことを考慮すると、ドライバ割り込みがトリガされたときにユーザー空間アプリケーションに通知できます。

添付:/proc/interruptsボタン(IRQ 45)を切り替えると、実際に割り込みカウンタが増えることがわかります。しかし、私はユーザープログラムでそのようなイベントを待つかポーリングするために使用できるインターフェースを知りません。おそらく、この質問を読んでいる他の人がこれを解決策として利用する方法を知っているかもしれません。

関連情報