Создание модуля ядра линукс и програмки к этому модулю.

Вопросы программного кода и архитектуры Linux

Модератор: Olej

PaiMeiPetrovich
Писатель
Сообщения: 36
Зарегистрирован: 26 авг 2022, 20:56
Контактная информация:

Re: Создание модуля ядра линукс и програмки к этому модулю.

Непрочитанное сообщение PaiMeiPetrovich » 29 авг 2022, 21:14

В общем, поизвращался я над программой! Изменить имя файла оказалось не такой простой задачей...
Насколько я понял, мне в один присест надо изменять и период и имя файла, то есть сразу все считать...
В итоге я все изменения кидаю в один буфер...Не знаю, по-варварски как-то вышло :lol:
Вложения
user_prog.c
(1.07 КБ) 32 скачивания
mod_loop.c
(3.26 КБ) 30 скачиваний
fops_rw.c
(1.86 КБ) 28 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Создание модуля ядра линукс и програмки к этому модулю.

Непрочитанное сообщение Olej » 29 авг 2022, 22:55

PaiMeiPetrovich писал(а):
29 авг 2022, 21:14
Насколько я понял, мне в один присест надо изменять и период и имя файла, то есть сразу все считать...
В итоге я все изменения кидаю в один буфер...
Я бы так не делал.
И так не делают в существующих проектах.
Если вам нужно иметь 2 управляемых параметра, то создайте 2 имени в /proc (я именно для этого создал отдельный каталог /proc/mod_loop):
- /proc/mod_loop/period - для работы с периодом повторения
- /proc/mod_loop/file - для работы с именем файла
И для 2-х файловых имён /proc/mod_loop/period и /proc/mod_loop/file иметь разные операции чтения/записи ... точнее разные таблицы операций struct proc_ops.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Создание модуля ядра линукс и програмки к этому модулю.

Непрочитанное сообщение Olej » 29 авг 2022, 23:15

Olej писал(а):
29 авг 2022, 22:55
И для 2-х файловых имён /proc/mod_loop/period и /proc/mod_loop/file иметь разные операции чтения/записи ...
И тогда вам для тестирования модуля не нужны никакие свои тестовые программы - всё тестирование и отладка делается с помощью cat и echo ... и других стандартных утилит пишущих и читающих. При этом решается попутно важнейшая задача: проверка своего творения на совместимость с POSIX стандартами! (потому что сами утилиты все - совместимые!).

А только потом, если кому-то очень захочется, пишем элементарную пользовательскую программу, которай делает простейшие вещи как:

Код: Выделить всё

main() {
...
   int fd1= open("/proc/mod_loop/period", ...);
   read(fd1, ... );
   write(fd1, "20", ...);
...   
   int fd2= open("/proc/mod_loop/file", ...);
   read(fd2, ... );
   write(fd2, "new_file", ...);
...
}

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Создание модуля ядра линукс и програмки к этому модулю.

Непрочитанное сообщение Olej » 30 авг 2022, 00:46

Olej писал(а):
29 авг 2022, 22:55
Я бы так не делал.
Обратите вниманиена функцию чтения /proc/mod_loop/period как я её сделал:

Код: Выделить всё

static char buf_msg[LEN_MSG + 1];

static ssize_t node_read(struct file *file, char *buf,
                         size_t count, loff_t *ppos) {
   static bool first = false;
   int res;
   if ((first = !first)) {
      sprintf(buf_msg, "%u", period);
      printk("! return %lu bytes: <%s>\n", strlen(buf_msg), buf_msg);
      strcat(buf_msg, "\n");
      res = copy_to_user((void*)buf, buf_msg, strlen(buf_msg));
      return strlen(buf_msg);
   } else {
      *ppos = 0;
      printk("! return EOF\n");
      return 0;
   }
}
Вас никак не удивляет флаг first и зачем это сделано?
А затем, что семантика POSIX операции ssize_t read(int fd, void *buf, size_t count); - предписывает:
- операция read читает count байт из дескриптора fd ...
- и смещает позицию чтения, offset, файлового дескриптора на count ...
- и так до тех пор (в цикле), пока не будет прочитано ssize_t = 0 байт - что означает конец файла, EOF, и на этом цикл чтений нужно прекращать.

И эту семантику стандарта POSIX знает и исполняет утилита cat ... как и все утилиты Linux!
И cat будет читать 2 раза - 1 раз число, и следующий раз 0 байт, что будет означать что читать больше нечего.
И так же точно как все утилиты Linux эти принципы POSIX и Linux должны знать и исполнять и мы, даже когда это не требуется по техзаданию!!!
Вот в той операции node_read() мы могли бы тупо возвращать при каждом вызове своё число ... и на всё остальное забить. Но здесь при 1-м чтении возвращается число, а при следующем - EOF, что позволяет читающей программе после этого сделать close() для читаемого дескриптора файла.

P.S. Даже эта показанная реализация искусственно упрощённая - потому что запрос числа читаемых байт может быть короче, чем длина имеющегося у нас результата, и тогда мы должны возвращать по частям строку результата.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Создание модуля ядра линукс и програмки к этому модулю.

Непрочитанное сообщение Olej » 30 авг 2022, 00:58

Olej писал(а):
30 авг 2022, 00:46
P.S. Даже эта показанная реализация искусственно упрощённая - потому что запрос числа читаемых байт может быть короче, чем длина имеющегося у нас результата, и тогда мы должны возвращать по частям строку результата.
И для более длинного результата, имени файла, /proc/mod_loop/file - чтение должно бы делаться корректно как-то так ... я взял просто готовый фрагмент из своей книги, по этому типу:

Код: Выделить всё

static char *get_rw_buf(void) {
   static char buf_msg[LEN_MSG + 1] =
          ".........1.........2.........3.........4.........5\n";
   return buf_msg;
}

// чтение из /proc/mod_proc :
static ssize_t node_read(struct file *file, char *buf,
                         size_t count, loff_t *ppos) {
   char *buf_msg = get_rw_buf();
   int res;
   LOG("read: %ld bytes (ppos=%lld)\n", (long)count, *ppos);
   if(*ppos >= strlen(buf_msg)) {       // EOF
      *ppos = 0;
      LOG("EOF");
      return 0;
   }
   if(count > strlen(buf_msg) - *ppos)
      count = strlen(buf_msg) - *ppos;   // это копия
   res = copy_to_user((void*)buf, buf_msg + *ppos, count);
   *ppos += count;
   LOG("return %ld bytes\n", (long)count);
   return count;
}
Т.е., если бы был такой цикл чтения в текстовой задаче - такое вполне может быть, читать по одному байту:

Код: Выделить всё

   int res;
   do {
      if((res = read(df, p, 1)) >= 0) {
         ...
      }
      else printf("read device error: %m\n");
   } while (res > 0);
- то строка "file", к примеру, должна читаться 5 (не 4!) раз: 1, 1, 1, 1, 0 байт.
А функция чтения в модуле (обеспечивающая операцию) должна обеспечивать именно такое поведение.

PaiMeiPetrovich
Писатель
Сообщения: 36
Зарегистрирован: 26 авг 2022, 20:56
Контактная информация:

Re: Создание модуля ядра линукс и програмки к этому модулю.

Непрочитанное сообщение PaiMeiPetrovich » 30 авг 2022, 12:57

Olej писал(а):
30 авг 2022, 00:46
Вас никак не удивляет флаг first и зачем это сделано?
Точно, удивило, забыл записать (и задать соответственно) этот вопрос!
Olej писал(а):
29 авг 2022, 22:55
И для 2-х файловых имён /proc/mod_loop/period и /proc/mod_loop/file иметь разные операции чтения/записи ... точнее разные таблицы операций struct proc_ops
Ну да, и просто 2 open() сделать...
Olej писал(а):
29 авг 2022, 23:15
И тогда вам для тестирования модуля не нужны никакие свои тестовые программы - всё тестирование и отладка делается с помощью cat и echo
Тут у меня именно по заданию программку надо было сделать. (ну а так да,понял про cat i echo)
Ну, прямо класс, много инфы полезной и по коду, и по линуксу, и по проганью в целом...Даже не знаю, как вас отблагодарить! :-D
Хочется даже просто какую-нибудь штуковину закинуть на форум, шоб ее с вами пообсуждать! Думаю, недельки через 2 так и сделаю, а пока пойду задания на с# и на голэнге делать... 8-)

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Создание модуля ядра линукс и програмки к этому модулю.

Непрочитанное сообщение Olej » 30 авг 2022, 13:05

PaiMeiPetrovich писал(а):
30 авг 2022, 12:57
Тут у меня именно по заданию программку надо было сделать. (ну а так да,понял про cat i echo)
Программу можно сделать, и даже не одну ... но потом!
Когда модуль ядра будет отлажен с помощью cat и echo (и всех других утилит Linux), которые заодно покажут совместимость со стандартами POSIX, со всеми пользовательскими API: open(), read(), write(), close(), fcntl() и мн. другими ... оно если с несколькими совместимо - то со всеми другими тоже совместимо будет.

Ответить

Вернуться в «Linux изнутри»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 10 гостей