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 уже нет.
При крайней нужде это можно и обойти ... как описывается в "расширенные возможности" ... но нет смысла, потому как у нас остаются другие способы.