Рано или поздно наступает необходимость выполнения в модуля ядра полезных операций. И наверное самым полезным в этом плане инструментом являются потоки ядра.
В качестве примера создания потока в модуле ядра я решил написать модуль, который будет каждую секунду вываливать в dmesg сообщение. Такой себе флудо-модуль ядра.
Для работы с потоками (их кстати в ядре linux зовут kthread) необходимо заинклудить linux/kthread.h.
В функции инициализации модуля необходимо запустить новый поток при помощи функции kthread_run. Ей нужно передать указатель функции потока, указатель на данные, которые будут переданы функции и название.
static int __init blablamod_init( void ) {
printk(KERN_NOTICE "Blablamod: %s():\n", __func__);
printk(KERN_NOTICE "Blablamod: HS: %d.\n", HZ);
task = kthread_run(&thread_function,(void *)data,"Blablathread");
return 0;
}
В ответ функция вернет нам указатель на созданный поток, который я объявил так:
static struct task_struct *task;
По обычаю при выгрузке модуля нужно вернуть все как было (остановить поток).
static void __exit blablamod_exit( void ) {
kthread_stop(task);
printk(KERN_NOTICE "Blablamod unloaded!\n" );
}
В функции потока реализован бесконечный цикл, который и флудит. В нем при помощи jiffies организована задержка.
int thread_function(void *data)
{
unsigned long tm = jiffies + msecs_to_jiffies(1000);
printk(KERN_NOTICE "Blablamod: %s(): data = %d.\n", __func__, (int)data);
while(!kthread_should_stop()){
if (time_after(jiffies, tm))
{
tm = jiffies + msecs_to_jiffies(1000);
printk(KERN_NOTICE "Blablamod: %s(): %lu.\n", __func__, jiffies);
}
schedule();
}
return 0;
}
Данная функция выводит полученные в качестве переменной данные, после чего выполняет цикл, пока не получит сигнал о завершении при помощи функции kthread_should_stop(). Вывод в консоль осуществляется примерно через секунду, если же время еще не настало управление отдается планировщику.
Задержка организована при помощи функции time_after, которая проверяет больше ли текущее время в jiffies чем заданное во втором параметре. Если больше то изменяем значение в переменной tm и выводим привет в dmesg.
Скомпилируйте и загрузите модуль. Теперь можно проверить создан ли поток.
$ dmesg .... [ 3477.526076] Blablamod: blablamod_init(): [ 3477.526119] Blablamod: HS: 100. [ 3477.530524] Blablamod: thread_function(): data = 85. [ 3478.537524] Blablamod: thread_function(): 317821. [ 3479.547541] Blablamod: thread_function(): 317922. [ 3480.557670] Blablamod: thread_function(): 318023.
Если не доверяем выводу:
$ ps -ef | grep bla root 8514 2 98 20:28 ? 00:00:09 [Blablathread]
Не забываем выгрузить модуль. Ато в логе будет ад.
Исходники на GitHub.




