Ядро Linux: вызывать функцию обратного вызова в пространстве пользователя из пространства ядра

Я пишу приложение пользовательского пространства Linux. где я хочу вызвать зарегистрированную функцию обратного вызова в области пользовательского пространства из пространства ядра.

то есть прерывание, поступающее на вывод GPIO (событие нажатия переключателя), и зарегистрированная функция вызывается в пользовательском пространстве.

есть ли способ сделать это.

Спасибо


person Akash Gajjar    schedule 06.07.2017    source источник
comment
Я думаю, что обычный способ сделать это — отправить драйверу устройства сигнал SIGIO процессу. Процесс регистрирует обработчик сигнала, который выполняет обратный вызов.   -  person Barmar    schedule 06.07.2017
comment
github.com/brgl/libgpiod. @Barmar, похоже, у тебя есть унаследованные знания по теме :-)   -  person 0andriy    schedule 07.07.2017
comment
также есть модуль Python с именем python-sysfs-gpio.   -  person Fl0v0    schedule 07.07.2017
comment
@ FI0v0, не используй его. Это устаревшие вещи, оставленные для обратной совместимости.   -  person 0andriy    schedule 08.07.2017
comment
@0andriy вау, я этого не знал. есть еще информация по этой теме? может быть в списке рассылки? Мне нужен был интерфейс Python для gpios, и все, что я тогда нашел, это python-sysfs-gpio. Если это унаследовано, необходим новый интерфейс Python.   -  person Fl0v0    schedule 10.07.2017
comment
@ Fl0v0, см. мой комментарий выше со ссылкой на новую библиотеку брендов. Я не знаю, есть ли у него привязка к Python.   -  person 0andriy    schedule 10.07.2017
comment
@0andriy У него еще нет привязок к Python :( github.com/brgl/libgpiod/issues/ 5   -  person Fl0v0    schedule 12.07.2017
comment
@Fl0v0, что означает, что у кого-то есть отличный шанс прославиться.   -  person 0andriy    schedule 12.07.2017


Ответы (2)


Я нашел приведенный ниже код после долгих копаний, и он отлично работает для меня.

Обработка прерываний от GPIO Во многих случаях вход GPIO можно настроить для генерации прерывания при изменении состояния, что позволяет вам ждать прерывания, а не опрашивать его в неэффективном программном цикле. Если бит GPIO может генерировать прерывания, граница файла существует. Изначально он имеет значение none, что означает, что прерывания не генерируются. Чтобы разрешить прерывания, вы можете установить одно из следующих значений: • нарастание: прерывание по переднему фронту • падение: прерывание по заднему фронту • оба: прерывание как по нарастающему, так и по заднему фронту • нет: нет прерываний (по умолчанию) Вы можете подождать прерывание с использованием функции poll() с POLLPRI в качестве события. Если вы хотите дождаться переднего фронта на GPIO 48, вы сначала разрешаете прерывания:

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

#echo растет > /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; 
}
person Akash Gajjar    schedule 11.10.2017
comment
Не работает для меня. Я не уверен, почему, хотя. Код срабатывает сразу при первом запуске, но никогда больше, когда я запускаю дальнейшие прерывания. Я сравниваю свой код с этой ссылкой: developer.ridgerun. com/wiki/index.php/Gpio-int-test.c, чтобы увидеть, что я делаю по-другому. Я знаю, что запускаются дальнейшие прерывания, потому что мой драйвер уровня ядра, который отслеживает одно и то же прерывание, каждый раз перехватывает его. Я обновлю это, когда выясню, что происходит не так. - person Eliezer Miron; 16.04.2019
comment
Оказывается, использование gpio.h для настройки прерываний работает только на уровне ядра. Мне также нужно было изменить значение края с пользовательского уровня, чтобы заставить его работать. Но теперь работает отлично! - person Eliezer Miron; 16.04.2019
comment
О, и в строке 15, я думаю, вам не хватает /value после /sys/class/gpio/gpio48 - person Eliezer Miron; 16.04.2019

Необходимо реализовать обработчик в модуле ядра, который запускает, например. символьное устройство. Из пользовательского пространства к нему можно было получить доступ путем опроса (например, ioctl() вызовов). Кажется, что это единственный способ на данный момент.

person renonsz    schedule 12.12.2017