Потоки в модуле ядра Linux

Рано или поздно наступает необходимость выполнения в модуля ядра полезных операций. И наверное самым полезным в этом плане инструментом являются потоки ядра.
В качестве примера создания потока в модуле ядра я решил написать модуль, который будет каждую секунду вываливать в 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.

 

Похожий код:

Фото аватара
Алексей Петров

Программист, разработчик с 5 летним опытом работы. Учусь на разработчика игр на Unity и разработчика VR&AR реальности (виртуальной реальности). Основные языки программирования: C#, C++.

Оцените автора
Бла, бла код
Добавить комментарий