лучший способ общаться и синхронизировать между ядром и пользовательским пространством в Linux - PullRequest
0 голосов
/ 15 декабря 2010

Моя цель - регистрировать множество действий из ядра.Для этого мне нужно записать в дисковые файловые системы.

Итак, я реализовал драйвер символьного устройства и процесс пространства пользователя, который читает с этого виртуального устройства.Драйвер копирует данные в буфер пространства пользователя, а пользовательский процесс записывает их в файл.

Моя проблема в том, как синхронизировать данные.Я начал использовать kfifo в реализации ядра для fifo.Поэтому, где бы я ни захотел войти, я использую API kfifo для копирования данных в fifo.Драйвер виртуального устройства считывает данные с fifo и копирует их в пространство пользователя.Поскольку регистрируемые данные огромны, мне нужна синхронизация, например, в потребителе производителя.Есть ли такая поддержка в ядре Linux, которую я могу использовать?

Решает ли сокет netlink такую ​​проблему ??

Ответы [ 3 ]

0 голосов
/ 15 декабря 2010

Думаю, сокеты netlink послужат вашим целям лучше, чем char char. Ядро будет записывать в сокет всякий раз, когда захочет записать, а ваша пользовательская программа, которая будет ждать в этом сокете, будет читать из него и записывать его в файл.

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

0 голосов
/ 16 декабря 2010

Вы также можете использовать простые принципы двойной буферизации, если у вас много данных для регистрации и вы не хотите пропустить какие-либо данные журнала.

Я не уверен насчет kfifo, но в вызовах чтения вашего драйвера устройства вы можете перевести процесс userpace в спящий режим, если нет данных для чтения с устройства. И всякий раз, когда ядро ​​пишет в символьное устройство, оно может разбудить любые процессы, спящие на устройстве. Например,

In kernel
 struct logbufStruct {
   char *kbuf; //by kmalloc or any means you wish.
   int ptr; //ptr to next writeable byte in kbuf.
   size_t kbuf_size;
   unsigned int flags;
   wait_queue_head_t data_wait;
 }
 read(inode, filep, buf, size) {
  logbufStruct = filep->private_data
  if (!test_bit(HAS_DATA, &logbufstruct.flags))
    wait_event_interruptible(&logbufstruct->data_wait, 
           test_bit(HAS_DATA, &logbufstruct.flags)||
           test_bit(ERROR, &logbufstruct.flags));
  /*
   * When this call returns, you would either have woken up
   * on data available or some signal interrupt which you should
   * handle in your character device and set appropriate flags.
   */
    if (test_bit(ERROR, &logbufstruct.flags) return -1;
    numbytes = copy_data(logbufStruct, buf, size);
    if(!has_more_data(logbufstruct)) clear_bit(HAS_DATA, &logbufstruct.flags);
    return numbytes;
 }

 /* This is the function your modules would call to log data
  * to be sent to userspace.
  */
 int mylogger_log(logbufstruct, char *msg, size_t n)
 {
   if (logbufstruct->ptr + n > logbufstruct->kbuf_size)
      return -1;
   copy the data.
   wake_up_interruptible(&logbufstruct->data_wait);
 }
 //initialization
  init_waitqueue_head(&logbufstruct->data_wait);
  logbufstruct->kbuf = kmalloc or whatever way you have to allocate
   space for holding log messages in memory.
0 голосов
/ 15 декабря 2010

Возможно, вы захотите использовать интерфейс реле, см. Documentation/filesystems/relay.txt.

...