커널 플랫폼 드라이버에서 사용자 공간 이벤트 생성

커널 플랫폼 드라이버에서 사용자 공간 이벤트 생성

문맥

플랫폼 드라이버온칩 구성 요소 및 기타 검색할 수 없는 장치용으로 작성된 장치 드라이버입니다. 이런 경우에 제가 집중하고 있는 것은SNVS 전원 켜기/끄기 드라이버i.MX6 기반 플랫폼에 적용 가능합니다.

질문

나는 플랫폼의 켜기/끄기 버튼이 전환될 때 사용자 공간 프로그램이 정보를 얻을 수 있기를 원합니다. 나는 두 가지 가능한 접근 방식을 식별하고 적어도 하나를 제거했습니다.

  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)을 전환하면 실제로 인터럽트 카운터가 증가하는 것을 볼 수 있습니다. 그러나 나는 사용자 프로그램에서 그러한 이벤트를 기다리거나 폴링하는 데 사용할 수 있는 인터페이스를 모릅니다. 어쩌면 이 질문을 읽는 다른 사람이 이것을 솔루션으로 활용하는 방법을 알고 있을 수도 있습니다.

관련 정보