LINUX.ORG.RU

Kernel development HELP


0

0

! Есть у нас модуль, который по определённому событию должен запустить некоторый скрипт - как это сделать?

! Как нормально обработать нажатие клавиши (как перехватить прерывание от клавы, чтобы при выгрузке модуля всё продолжало работать)

Заранее спасибо за ваши ответы.

anonymous

Мнда... По первому вопрсу смотри в сторону /proc и как сделать acpi драйвер. Ну а проще создать устройство, и при событии писать в него определённую информацию, написать демон на C, который будет в selectе ждать данных с этого устройства. По второму, модуль ядра не должен напрямую работать с клавиатурой!

krum
()
Ответ на: комментарий от krum

при нажатии клавиши необходимо запускать скрипт. Если не "на прямую", то как лучше?

Запуск скрипта должен производиться без дополнительного user-space демона.

anonymous
()
Ответ на: комментарий от anonymous

Ээээ, а не проще слущать /dev/console или что-там-у-вас? Из kernel-space нельзя( вернее можно, но очень сложно) запустить программу. Объясниет, зачем вам нужен именно kernel-module? Чем не устраивает user-space daemon?

krum
()
Ответ на: комментарий от krum

Дело в том, что есть огромное желание податься в kernel developers, но опыта в этом деле на уровне hello world`a :( Сейчас подыскиваю соответствующую работу и то, что я здесь привожу - фрагмент тестового задания. Пытаюсь кое-что найти в internet, но получается пока не очень, вот решил сюда написать...

anonymous
()

ytfyt

1) exec_usermodehelper() 2) пропишите свой обработчик в IDT (если речь о x86) :)))

непонятно что именно вы хотите сделать

int_0dh
()
Ответ на: комментарий от anonymous

> Пытаюсь кое-что найти в internet

LDD3 и соответствующие статьи на lwn.net

tailgunner ★★★★★
()
Ответ на: ytfyt от int_0dh

хочу написать модуль, который будет по нажатию сочетания клавиш запускать скрипт, не используя при этом дополнительного user-space демона. Вот и пытюсь понять как это сделать. Хоть примеры какие в ядре подходящие найти... короче голова болит ужо :-\

anonymous
()
Ответ на: комментарий от anonymous

ytfyt

если ядро сравнительно свежее то никаких прерываний вам перехватывать не нужно а нужно зарегистрировать свой input_handler, а в евенте смотреть на полученный код клавиши. и если он вас устраивает то запускать скрипт через call_usermodehelper(). соответсно при выходе модуля грохнуть этот скрипт (если он еще висит).

int_0dh
()
Ответ на: ytfyt от int_0dh

ytfyt

вот очень кривой и некрасивый быстро сляпанный код который делает примерно что
что вам нужно:

коментов нет принципиально. код полурабочий но общую идею вы должны уловить.

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/mm.h>
#include <linux/kbd_kern.h>
#include <linux/kbd_diacr.h>
#include <linux/input.h>

#define START_SCRIPT 0x1
#define STOP_SCRIPT  0x2

static int cmd = 0;
static DECLARE_MUTEX(run_sem);
static char *argv[] = {"test_script", NULL};
static char *envp[] = {"TERM=linux", NULL};

static int script_runner(void *unused) {
   for (;;) {
       down(&run_sem);
       switch (cmd) {
          case START_SCRIPT:
            (void)call_usermodehelper("/test/test_script",
    argv, envp, 1);
          case STOP_SCRIPT:
          break;
        }
   }
  return 0;
}

static void test_event(struct input_handle *h, unsigned int e_type,
unsigned int e_code, int value) {
  if (e_type == EV_KEY)
   if (e_code == KEY_LEFTALT) {
     cmd = START_SCRIPT;
     up(&run_sem);
   }
}

static
struct input_handle *test_connect(
 struct input_handler *h, struct input_dev *d,
struct input_device_id *id) {
 struct input_handle *res = NULL;
 int i = 0;
 for (i = KEY_RESERVED; i < BTN_MISC; i++)
  if (test_bit(i, dev->keybit))
    break;
  if (i == BTN_MISC && !test_bit(EV_SNDm, dev->ebit))
    return NULL;
 res = kmalloc(sizeof(*res), GFP_KERNEL);
 memset(res, 0, sizeof(*res));
 res->dev = dev;
 res->handler = h;
 res->name = "k_test";
 input_open_device(res);
 return res;
}

static void test_disconnect(struct input_handler *h) {
   input_close_device(h);
   kfree(h);
}

static struct input_device_id test_table[] = {
{
  .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
  .evbit = { BIT(EV_KEY) },
},
{
  .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
  .evbit = { BIT(EV_KEY) },
},
{},
};

static struct input_handler test_handler = {
 .event = test_event,
 .connect = test_connect,
 .disconnect = test_disconnect,
 .name = "k_test",
 .id_table = test_table,
};

int init_module() {
  input_register_handler(&test_handler);
  (void)kernel_thread(script_runner, NULL, 0);
  return 0;
}

void cleanup_module()
{
   input_unregister_module(&test_handler);
}

int_0dh
()
Ответ на: ytfyt от int_0dh

Спасибо за помощь!

anonymous
()
Ответ на: ytfyt от int_0dh

Осталась последняя проблема - как создать, а потом уничтожить файл устройства из пространства модуля. В LDD3 предлагается это делать скриптом из userspace, в коде ядря не могу найти примера... вобщем уже и не знаю где искать это... Если создавать файл устройства из userspace, то обмен через него идёт - никаких проблем, но как-то это не очень правильно.

anonymous
()
Ответ на: комментарий от anonymous

> В LDD3 предлагается это делать скриптом из userspace

Почитай внимательно главу LDD3, посвященную Linux Device Model, там всё описано.

tailgunner ★★★★★
()
Ответ на: ytfyt от int_0dh

> быстрый и тупой способ - использовать vfs_mknod()

За это - три года расстрела на месте через повешение на гитарной струне.

tailgunner ★★★★★
()
Ответ на: комментарий от krum

> Опят же использовать call_usermodehelper(), и вызывать соответственно mknod и rm.

Ладно, за это - три года расстрела, но без повешения.

Народ, перестаньте страдать дурью и демонстрировать нестандартное мышление. Всё решено до нас, стандартные решения опубликованы.

tailgunner ★★★★★
()
Ответ на: ytfyt от int_0dh

> а в чем собственно дело ? что именно вам не нравится ? :))

Пара вещей: 1) ты посоветовл начинающему залезть в VFS. Не знаю, понимаешь ли ты все правла и всю ответственность работы в VFS, но он - не понимает точно; 2) ты предлагаешь использовать вместо описанных и предназначенных для определенной цели мало описанный API, предназначенный совсем для другого. В результате у получится драйвер, который ведет себя не так, как ведут себя другие драйверы - я ненавижу, когда это делается из лени, невежества или недомыслия (не знаю, что из этого относится к тебе).

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

ytfyt

>2) ты предлагаешь использовать вместо >описанных и предназначенных для >определенной цели мало описанный API, >предназначенный совсем для другого
а для чего по вашему предназначена vfs_mknod() как не для создания файла устройства ? нет, конечно намного кошернее и проще
зарегестрироваться в sysfs и настроить udev, но не всегда это применимо (речь идет о тестовом задании)
>я ненавижу, когда это делается из лени, >невежества или недомыслия (не знаю, что >из этого относится к тебе).
я и сам это очень не люблю :)

int_0dh
()
Ответ на: ytfyt от int_0dh

> а для чего по вашему предназначена vfs_mknod() как не для создания файла устройства ?

Я знаю, для чего она точно _не предназначена_ - для создания файлов устройств непосредственным вызовом из драйвера.

> конечно намного кошернее и проще зарегестрироваться в sysfs и настроить udev, но не всегда это применимо

Я так сразу и не могу придумать ситуацию, когда это невозможно. Пример приведешь?

> (речь идет о тестовом задании)

Как раз в тестовом задании всё нужно сделать по стандарту.

>>я ненавижу, когда это делается из лени, >невежества или недомыслия (не знаю, что из этого относится к тебе).

>я и сам это очень не люблю :)

Ну так и не советуй.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

ytfyt

>Я так сразу и не могу ридумать >ситуацию, когда это невозможно. Пример >приведешь? ну например есть маленькая глупенькая платка и на ней ядро < 2.6. Тут даже devfs слишком жирно, не говоря уже о том, что его нету под 2.2 (которое еще в production :) )

в целом с наездом согласен, каюсь :)

int_0dh
()
Ответ на: ytfyt от int_0dh

> ну например есть маленькая глупенькая платка и на ней ядро < 2.6. Тут даже devfs слишком жирно, не говоря уже о том, что его нету под 2.2

Если ядро < 2.6, да еще драйвер влинкован в ядро статически - тогда конечно :) Но в вопросе речь шла о динамической загрузке, так что проще и лучше (на < 2.6) сделать mknod в скрипте загрузки, и rm - в скрипте выгрузки (или настроить modules.conf соответственно).

tailgunner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.