【问题标题】:Linux Kernel: invoke call back function in user space from kernel spaceLinux Kernel:从内核空间调用用户空间的回调函数
【发布时间】:2017-12-10 12:38:20
【问题描述】:

我正在编写 Linux 用户空间应用程序。我想从内核空间调用用户空间区域中的注册回调函数。

即中断到达 GPIO 引脚(开关按下事件)并在用户空间调用注册函数。

有什么方法可以做到这一点。

谢谢

【问题讨论】:

  • 我认为通常的方法是让设备驱动程序向进程发送SIGIO 信号。进程注册一个执行回调的信号处理程序。
  • github.com/brgl/libgpiod。 @Barmar,看起来您对主题有传统知识:-)
  • 还有一个名为python-sysfs-gpio的python模块。
  • @FI0v0,不要使用它。这是为了向后兼容而留下的遗留内容。
  • @0andriy 哇,我不知道。有没有关于这个主题的更多信息?也许在邮件列表中?我需要一个用于 gpios 的 python 接口,而当时我发现的只是 python-sysfs-gpio。如果这是遗留问题,则需要新的 python 接口。

标签: linux linux-kernel linux-device-driver embedded-linux


【解决方案1】:

经过大量挖掘,我找到了下面的代码,非常适合我。

处理来自 GPIO 的中断 在许多情况下,可以将 GPIO 输入配置为在 更改状态,允许您等待中断而不是轮询 低效的软件循环。如果 GPIO 位可以产生中断,文件边缘 存在。最初,它的值为 none ,这意味着它不会产生中断。 要启用中断,您可以将其设置为以下值之一: • 上升:上升沿中断 • 下降:下降沿中断 • both:在上升沿和下降沿均中断 • none:无中断(默认) 您可以使用 poll() 函数将 POLLPRI 作为事件来等待中断。如果 要等待 GPIO 48 的上升沿,首先启用中断:

#echo 48 > /sys/class/gpio/export

#echo rise > /sys/class/gpio/gpio48/edge

然后,您使用 poll() 等待更改,如下代码示例所示:

 #include <stdio.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <poll.h>>

 int main(void) {

         int f;
         struct pollfd poll_fds [1];
         int ret;
         char value[4];
         int n;

         f = open("/sys/class/gpio/gpio48", O_RDONLY);
         if (f == -1) {
              perror("Can't open gpio48");
              return 1;
         }

         poll_fds[0].fd = f;
         poll_fds[0].events = POLLPRI | POLLERR;

         while (1) {
              printf("Waiting\n");

              ret = poll(poll_fds, 1, -1);
              if (ret > 0) {
                  n = read(f, &value, sizeof(value));
                  printf("Button pressed: read %d bytes, value=%c\n", n, value[0]);
              }
         }     
      return 0; 
}

【讨论】:

  • 对我不起作用。不过,我不确定为什么。代码在第一次运行时立即触发,但当我触发进一步的中断时就再也不会触发了。我正在将我的代码与此链接进行比较:developer.ridgerun.com/wiki/index.php/Gpio-int-test.c 以了解我在做什么不同。我知道正在触发进一步的中断,因为我的内核级驱动程序监视相同的中断每次都在捕获它。当我弄清楚出了什么问题时,我会更新这个。
  • 原来,使用 gpio.h 配置中断仅在内核级别有效。我还需要从用户级别更改边缘值以使其正常工作。但现在效果很好!
  • 哦,在第 15 行,我认为您在“/sys/class/gpio/gpio48”之后缺少“/value”
【解决方案2】:

必须在内核模块中实现一个处理程序来触发,例如一个字符设备。从用户空间可以通过轮询(例如ioctl() 调用)来访问它。看来是目前唯一的办法了。

【讨论】:

    猜你喜欢
    • 2011-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-08
    • 2012-06-21
    • 2011-07-11
    相关资源
    最近更新 更多