Форум по операционной системе GNU/Linux и свободному программному обеспечению
Текущее время: 24 апр 2019, 07:19

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 56 ]  На страницу Пред.  1, 2, 3, 4, 5, 6  След.
Автор Сообщение
 Заголовок сообщения: Re: практикум по Linux Kernel
Непрочитанное сообщениеДобавлено: 10 мар 2015, 23:39 
Не в сети
Писатель
Аватара пользователя

Зарегистрирован: 24 сен 2011, 14:22
Сообщения: 11699
Откуда: Харьков
Olej писал(а):
Вам не говорили, что код вашего модуля ядра может читать и писать файлы на диске?
Сейчас глянем как это происходит...


Поехали дальше...

Задача (*): Пусть модуль читает при загрузке из конфигурационного файла произвольное число каналов данных, каждый из которых записан конфигурационной строкой вида chan=dev123, где dev123 — это будет имя устройства /dev/dev123, в которое можно писать данные произвольной длины, а потом читать оттуда записанное.

Подсказка: Используйте код ранее сформулированной задачи (см. ранее), о записи-чтении данных произвольной длины в устройство (циклический кольцевой буфер), пример queue.tgz.

Я не буду здесь выписывать код - он достаточно объёмный ... почему и задача отмечена (*), но всё есть в архиве.
А выглядит это как-то так:
Код:
bash-4.2$ sudo insmod confm.ko file=/etc/xxx.cfg debug=1
bash-4.2$ ls -l /dev/x*
crw-rw-rw- 1 root root 10, 58 мар 10 21:35 /dev/x123
crw-rw-rw- 1 root root 10, 57 мар 10 21:35 /dev/xx456
bash-4.2$ echo 12345 > /dev/x123
bash-4.2$ cat /dev/x123
12345
bash-4.2$ echo aaaaaaaaaaaaaaaaaaaaaaaa > /dev/xx456
bash-4.2$ cat /dev/xx456
aaaaaaaaaaaaaaaaaaaaaaaa
bash-4.2$ dmesg | tail -n6
[22290.594685] + device name: /dev/x123
[22290.597053] + register device 10:56
[22290.597067] + device name: /dev/xx456
[22290.597179] + register device 10:55
[22488.283181] + deregister device 10:56
[22488.283421] + deregister device 10:55
bash-4.2$ cat /etc/confm.conf
# конфигурационный файл модуля confm.ko

chan=x123
chan = xx456
#chan= z789


Вложения:
confm.tgz [6.95 КБ]
Скачиваний: 245
Вернуться к началу
 Профиль Отправить личное сообщение Отправить email  
 
 Заголовок сообщения: Re: практикум по Linux Kernel
Непрочитанное сообщениеДобавлено: 11 мар 2015, 09:49 
Не в сети
Писатель
Аватара пользователя

Зарегистрирован: 24 сен 2011, 14:22
Сообщения: 11699
Откуда: Харьков
Задача: Сделайте свои собственные приложения (пространство пользователя), загружающее и выгружающее, соответственно, указанный модуль ядра (так как это делают insmod и rmmod ... но только лучше ;-) ).

Эта задача описана в основном тексте (в "Расширенные возможности"), поэтому комментировать не буду.
Только обращаю внимание ... на не тривиальную задачу.
Архив всё же задублирую.


Вложения:
umaster.tgz [3.21 КБ]
Скачиваний: 240
Вернуться к началу
 Профиль Отправить личное сообщение Отправить email  
 
 Заголовок сообщения: Re: практикум по Linux Kernel
Непрочитанное сообщениеДобавлено: 12 мар 2015, 02:26 
Не в сети
Писатель
Аватара пользователя

Зарегистрирован: 24 сен 2011, 14:22
Сообщения: 11699
Откуда: Харьков
Вот такая очень неплохая задача (вопрос), очень важная для расширенных возможностей программирования модулей:

Задача: Как рассмотреть все имена API, экспортируемые непосредственно ядром (не учитывая символов, экспортируемых другими динамически загруженными модулями)? Подсчитайте число таких имён в вашей системе.

Код:
[Olej@modules connections]$ cat /lib/modules/`uname -r`/build/Module.symvers | grep vmlinux | grep EXPORT_SYMBOL | wc -l
7522


Код:
[Olej@modules connections]$ cat /lib/modules/`uname -r`/build/Module.symvers | grep vmlinux | grep EXPORT_SYMBOL \
| head -n 10
0x00000000   ipv6_chk_custom_prefix   vmlinux   EXPORT_SYMBOL
0x00000000   sata_pmp_error_handler   vmlinux   EXPORT_SYMBOL_GPL
0x00000000   __cleancache_invalidate_page   vmlinux   EXPORT_SYMBOL
0x00000000   pcmcia_reset_card   vmlinux   EXPORT_SYMBOL
0x00000000   unregister_vt_notifier   vmlinux   EXPORT_SYMBOL_GPL
0x00000000   kmem_cache_alloc   vmlinux   EXPORT_SYMBOL
0x00000000   replace_page_cache_page   vmlinux   EXPORT_SYMBOL_GPL
0x00000000   __cond_resched_softirq   vmlinux   EXPORT_SYMBOL
0x00000000   set_anon_super   vmlinux   EXPORT_SYMBOL
0x00000000   rtc_class_open   vmlinux   EXPORT_SYMBOL_GPL


Здесь важно то, что из совершенно родственных вызовов (например системных вызовов), одни являются экспортируемыми, а другие нет:
Код:
[Olej@modules connections]$ cat /lib/modules/`uname -r`/build/Module.symvers | grep sys_open | grep EXPORT_SYMBOL
[Olej@modules connections]$ cat /lib/modules/`uname -r`/build/Module.symvers | grep sys_close | grep EXPORT_SYMBOL
0x00000000   sys_close   vmlinux   EXPORT_SYMBOL


Вернуться к началу
 Профиль Отправить личное сообщение Отправить email  
 
 Заголовок сообщения: Re: практикум по Linux Kernel
Непрочитанное сообщениеДобавлено: 12 мар 2015, 18:33 
Не в сети
Писатель
Аватара пользователя

Зарегистрирован: 24 сен 2011, 14:22
Сообщения: 11699
Откуда: Харьков
Olej писал(а):
Вот такая очень неплохая задача (вопрос), очень важная для расширенных возможностей программирования модулей:


Ещё несколько "хороших" задач (их все можно считать со *), из области расширенных возможностей программирования:

Задача: Замените один из стандартных системных вызовов Linux на свой, так, чтобы он обрабатывался вашим собственным кодом.

Задача: Расширьте один из стандартных системных вызовов Linux, так, чтобы перед выполнением системного вызова выполнялся ваш собственный кодом ... например, чтобы при выполнении open() любой программой, отчёт об этом open() ... отправлялся дяде Васе. ;-)

Задача: Сделайте то же, что в предыдущей задаче, но чтобы код вызывался не перед, а после отработки стандартного системного вызова Linux.

Задача: Добавьте новый системный вызов к стандартному набору Linux, так, чтобы только ваши приложения могли использовать возможности нового системного вызова.

Естественно, что все эти задачи - одной группы.

Я по ним не буду здесь приводить решений, потому что все эти решения есть и обсуждаются в сопроводительном тексте.
Обращаю только внимание, что они там есть.


Вернуться к началу
 Профиль Отправить личное сообщение Отправить email  
 
 Заголовок сообщения: Re: практикум по Linux Kernel
Непрочитанное сообщениеДобавлено: 12 мар 2015, 18:39 
Не в сети
Писатель
Аватара пользователя

Зарегистрирован: 24 сен 2011, 14:22
Сообщения: 11699
Откуда: Харьков
Olej писал(а):
Естественно, что все эти задачи - одной группы.


А вот очень славная задача совсем из другой области:

Задача: Напишите образец собственной файловой системы используя FUSE - Filesystem in Userspace, т.е. не нишучи ни одного оператора в пространстве ядра! Ваша файловая система должна выполнять обычные заурядные операции над файловыми системами: создавать иерархии каталогов командой mkdir, создание файлов командами touch, echo (с перенаправлением), копирование cp, переименование и перемещение mv ... ну, т.е. весь джентльменский набор.
Но всё это без права писать что-либо в режиме ядра.

P.S. См. сюда: файловая система FUSE.


Вернуться к началу
 Профиль Отправить личное сообщение Отправить email  
 
 Заголовок сообщения: Re: практикум по Linux Kernel
Непрочитанное сообщениеДобавлено: 16 мар 2015, 02:06 
Не в сети
Писатель
Аватара пользователя

Зарегистрирован: 24 сен 2011, 14:22
Сообщения: 11699
Откуда: Харьков
Olej писал(а):
Ещё несколько "хороших" задач (их все можно считать со *), из области расширенных возможностей программирования:


Ещё один "необъятный" класс для "хороших" задач из Linux kernel - это всё, что связано с параллельными потоками в ядре, многопроцессорностью, SMP и всё в этом духе...

Мультипроцессорность и параллелизм сами по себе одна из интереснейших и сложных тем в программировании вообще... но в kernel усугубляется тем, что:
- почти никто из широко распространённых операционных систем не предполагают параллельность внутри ядра;
- в Linux это тоже появилось не так давно, начиная с версий 2.6;
- это естественный механизм эффективного "натягивания" Linux на многоядерные SMP архитектуры (которые вскорости обещают стать много-много ядерными ;-) );
- и API для этого очень существенно отличается от подобного в пространстве приложений пользователя.


Вернуться к началу
 Профиль Отправить личное сообщение Отправить email  
 
 Заголовок сообщения: Re: практикум по Linux Kernel
Непрочитанное сообщениеДобавлено: 16 мар 2015, 02:13 
Не в сети
Писатель
Аватара пользователя

Зарегистрирован: 24 сен 2011, 14:22
Сообщения: 11699
Откуда: Харьков
Olej писал(а):
Ещё один "необъятный" класс для "хороших" задач из Linux kernel - это всё, что связано с параллельными потоками в ядре, многопроцессорностью, SMP и всё в этом духе...


Задача: Для начала просто "сосчитайте" сколько процессоров присутствуют в вашей системе (архитектуре).

Предупреждение: Гипертриэдинг система Linux (или все операционные системы вообще?) не отличает от реально присутствующих 2-х процессоров. Как их различить? (я не знаю)

Такую задачу можно решать разными способами.
Вот только один из них:
Код:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/smp.h>

short data_percpu[] = { 0, 0, 0, 0, 0, 0, 0 ,0 };
int size = sizeof( data_percpu ) / sizeof( data_percpu[ 0 ] );

void call_func( void* info ) {
   int cpu = get_cpu();
   if( cpu >= size ) {
      printk( KERN_INFO "CPU number %d grater %d\n", cpu, size );
      return;
   }
   data_percpu[ cpu ]++;
   put_cpu();
}

int test_nump( void ) {
   char msg[ 120 ] = ""; // = "CPU in use: "
   int i;
   on_each_cpu( call_func, NULL, 1 );
   for( i = 0; i < size; i++ )
      if( data_percpu[ i ] )
         sprintf( msg + strlen( msg ), "%d ", i );
   printk( KERN_INFO "CPU in use: %s\n", msg );
   return -1;
}

module_init( test_nump );
MODULE_LICENSE( "GPL" );
MODULE_AUTHOR( "Oleg Tsiliuric <olej@front.ru>" );

Код:
[Olej@modules tcreat]$ sudo insmod nproc.ko
insmod: ERROR: could not insert module nproc.ko: Operation not permitted
[Olej@modules tcreat]$ dmesg | tail -n1
[14061.226373] CPU in use: 0 1 2 3


Вложения:
nproc.c [797 байт]
Скачиваний: 235
Вернуться к началу
 Профиль Отправить личное сообщение Отправить email  
 
 Заголовок сообщения: Re: практикум по Linux Kernel
Непрочитанное сообщениеДобавлено: 16 мар 2015, 19:10 
Не в сети
Писатель
Аватара пользователя

Зарегистрирован: 24 сен 2011, 14:22
Сообщения: 11699
Откуда: Харьков
Olej писал(а):
Ещё один "необъятный" класс для "хороших" задач из Linux kernel - это всё, что связано с параллельными потоками в ядре, многопроцессорностью, SMP и всё в этом духе...


Задача: Вам предстоит выполнить некоторые ординарные действия в ядре, но параллельно, средствами потоков ядра. Создайте, как минимум, 4 разных способа формирования выполнения своих действий в отдельном потоке.

Вот так ... простенько и со вкусом.


Вернуться к началу
 Профиль Отправить личное сообщение Отправить email  
 
 Заголовок сообщения: Re: практикум по Linux Kernel
Непрочитанное сообщениеДобавлено: 16 мар 2015, 19:22 
Не в сети
Писатель
Аватара пользователя

Зарегистрирован: 24 сен 2011, 14:22
Сообщения: 11699
Откуда: Харьков
Olej писал(а):
Задача: Вам предстоит выполнить некоторые ординарные действия в ядре, но параллельно, средствами потоков ядра. Создайте, как минимум, 4 разных способа формирования выполнения своих действий в отдельном потоке.


1. Пользуясь старым вызовом kernel_thread().
Это тот способ, который наиболее полно описанный в литературе (рекомендуемый).
Код:
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/delay.h>

#define LOG(...) printk( KERN_INFO "! "__VA_ARGS__ )

// current - указатель на дескриптор текущей задачи
static int threadfn( void *data ) {
   struct completion *finished = (struct completion*)data;
   LOG( "%d: start time %lX\n", current->pid, jiffies );
   msleep( 1000 );                        // пауза 1с.
   complete( finished );                  // отмечаем факт выполнения условия
   LOG( "%d: finish time %lX\n", current->pid, jiffies );
   return 0;
}

int test_thread( void ) {
   DECLARE_COMPLETION( finished );
   unsigned long j = jiffies;
   pid_t pid;
   pid = kernel_thread( threadfn, &finished, CLONE_FS ); // запускаем новый поток
   wait_for_completion( &finished );                     // ожидаем выполнения условия
   j = jiffies - j;
   LOG( "%d: evaluation time was %ld millisec.\n", current->pid, 1000 * j / HZ );
   return -1;
}

module_init( test_thread );
MODULE_LICENSE( "GPL" );
MODULE_AUTHOR( "Oleg Tsiliuric <olej@front.ru>" );

Код:
[olej@fedora smp]$ time sudo insmod thr1.ko
Error: could not insert module thr1.ko: Operation not permitted
real    0m1.121s
user    0m0.041s
sys     0m0.071s

[olej@fedora smp]$ dmesg | tail -n3
[ 2425.969956] ! 3080: start time 207091
[ 2426.970216] ! 3080: finish time 20747A
[ 2426.970309] ! 3079: evaluation time was 1001 millisec.


Но! ...
Этот рекомендуемый литературой способ не будет работать в поздних ядрах:
Код:
[Olej@modules smp]$ uname -r
3.14.8-200.fc20.i686
[Olej@modules smp]$ sudo insmod thr1.ko
[sudo] пароль для Olej:
insmod: ERROR: could not insert module thr1.ko: Unknown symbol in module

При внимательном рассмотрении это можно понять ещё при компиляции:
Код:
[Olej@modules smp]$ make
make -C /lib/modules/3.18.9-100.fc20.x86_64/build M=/home/Olej/2015-WORK/GlobalLogic/PRACTIS.Kernel/PRACTIS.Tasks/+TASKS/smp modules
make[1]: Вход в каталог `/usr/src/kernels/3.18.9-100.fc20.x86_64'
  CC [M]  /home/Olej/2015-WORK/GlobalLogic/PRACTIS.Kernel/PRACTIS.Tasks/+TASKS/smp/thr1.o
  Building modules, stage 2.
  MODPOST 1 modules
WARNING: "kernel_thread" [/home/Olej/2015-WORK/GlobalLogic/PRACTIS.Kernel/PRACTIS.Tasks/+TASKS/smp/thr1.ko] undefined!
  CC      /home/Olej/2015-WORK/GlobalLogic/PRACTIS.Kernel/PRACTIS.Tasks/+TASKS/smp/thr1.mod.o
  LD [M]  /home/Olej/2015-WORK/GlobalLogic/PRACTIS.Kernel/PRACTIS.Tasks/+TASKS/smp/thr1.ko
make[1]: Выход из каталога `/usr/src/kernels/3.18.9-100.fc20.x86_64'

Вон тот WARNING видите? ;-)

Подзадача: Выясните почему? Что изменилось?
Подзадача: Начиная с какой версии ядра этот способ не работает?

Причина в том, что в новых ядрах функция (имя) kernel_thread() присутствует, но не экспортируется!
Код:
[olej@fedora smp]$ uname -r
3.6.11-5.fc17.i686
[olej@fedora smp]$ cat /lib/modules/`uname -r`/build/Module.symvers | grep kernel_thread
0x00000000      kernel_thread   vmlinux EXPORT_SYMBOL

Код:
[Olej@modules tcreat]$ uname -r
3.18.9-100.fc20.x86_64
[Olej@modules smp]$ cat /lib/modules/`uname -r`/build/Module.symvers | grep kernel_thread


На 2-ю подзадачу я не знаю ответа :-? ... но в ядре 3.6 он ещё работает, а в ядре 3.14 уже нет.

При крайней нужде это можно и обойти ... как описывается в "расширенные возможности" ... но нет смысла, потому как у нас остаются другие способы.


Вложения:
thr1.c [1.14 КБ]
Скачиваний: 240
Вернуться к началу
 Профиль Отправить личное сообщение Отправить email  
 
 Заголовок сообщения: Re: практикум по Linux Kernel
Непрочитанное сообщениеДобавлено: 16 мар 2015, 19:28 
Не в сети
Писатель
Аватара пользователя

Зарегистрирован: 24 сен 2011, 14:22
Сообщения: 11699
Откуда: Харьков
Olej писал(а):
Задача: Вам предстоит выполнить некоторые ординарные действия в ядре, но параллельно, средствами потоков ядра. Создайте, как минимум, 4 разных способа формирования выполнения своих действий в отдельном потоке.


2. Пользуясь новым вызовом kthread_run() (или kthread_create() ).
Код:
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/kthread.h>

#define LOG(...) printk( KERN_INFO "! "__VA_ARGS__ )

// current - указатель на дескриптор текущей задачи:
static int threadfn( void *data ) {
   struct completion *finished = (struct completion*)data;
   LOG( "%d: start time %lX\n", current->pid, jiffies );
   msleep( 1000 );                        // пауза 1с.
   complete( finished );                  // отмечаем факт выполнения условия
   LOG( "%d: finish time %lX\n", current->pid, jiffies );
   return 0;
}

int test_thread( void ) {
   DECLARE_COMPLETION( finished );
   unsigned long j = jiffies;
   struct task_struct *t = kthread_run( threadfn, &finished, "new_thread" );
   if( NULL == t ) return -EINVAL;
   wait_for_completion( &finished );      // ожидаем выполнения условия
   j = jiffies - j;
   LOG( "%d: evaluation time was %ld millisec.\n", current->pid, 1000 * j / HZ );
   return -1;
}

module_init( test_thread );
MODULE_LICENSE( "GPL" );
MODULE_AUTHOR( "Oleg Tsiliuric <olej@front.ru>" );

Код:
[Olej@modules smp]$ time sudo insmod thr2.ko
insmod: ERROR: could not insert module thr2.ko: Operation not permitted
real    0m1.034s
user    0m0.011s
sys     0m0.014s

[Olej@modules smp]$ dmesg | tail -n3
[20298.553347] ! 13267: start time 10130F51D
[20299.554329] ! 13267: finish time 10130F906
[20299.554338] ! 13266: evaluation time was 1001 millisec.


- kthread_run() - макрос, использующий kthread_create(), поэтому вы его не обнаружите в числе экспортируемых;
- с самим kthread_create() - осторожно, потому что он создаёт поток, но его ещё не запускает ... так ваш модуль и будет висеть вечно до перезагрузки... ;-)


Вложения:
thr2.c [1.13 КБ]
Скачиваний: 234
Вернуться к началу
 Профиль Отправить личное сообщение Отправить email  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 56 ]  На страницу Пред.  1, 2, 3, 4, 5, 6  След.

Часовой пояс: UTC + 3 часа


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

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


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

Найти:
Перейти:  
cron
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB
[ Time : 0.161s | 16 Queries | GZIP : On ]