Как использовать рабочую очередь Linux

Рабочие очереди Linux предназначены для потоков уровня ядра с контекстом процесса. Я пытался использовать его в качестве альтернативы kthread, который не имеет конкретного контекста процесса. Но как передать данные в очередь на работу? У work_struct есть поле данных, которое имеет тип atomic_long_t. Я не мог передать указатель на это поле. Как это сделать?

Также я не смог найти ни одного конкретного примера рабочей очереди. Вы можете предложить один?

Ответ 1

Если вы хотите передать данные в свою рабочую очередь, просто вставьте структуру work_struct внутри своей собственной структуры данных и используйте container_of внутри вашей рабочей функции для ее получения.

Что касается простого примера, ядро ​​полон его - просто git grep work_struct. Вы можете посмотреть на функцию drivers/cpufreq/cpufreq.c (handle_update) для простого примера. В приведенной ниже статье также представлен пример в конце, но он не использует container_of и вместо этого полагается на тот факт, что первый член структуры имеет тот же адрес, что и его родительский:

http://www.ibm.com/developerworks/linux/library/l-tasklets/index.html

Ответ 2

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

https://github.com/m0r3n/kernel_modules/blob/master/workQueue.c

Вы можете скомпилировать следующий файл Makefile:

KVERSION = $(shell uname -r)
obj-m = workQueue.o

all:
    make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
clean:
    make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean

Вставьте модуль:

# sync; insmod workQueue.ko; sync

И посмотрите журналы:

# tailf /var/log/kern.log

EDIT: Я просто добавил задержанную версию:

https://github.com/m0r3n/kernel_modules/blob/master/workQueueDelayed.c

Ответ 3

По умолчанию функция работы вызывается с работой, выполняемой как параметр. Внутри потока можно легко получить элемент данных структуры. Кроме того, Gnurou, чтобы получить доступ к большему количеству данных, структура работы может быть помещена в структуру, специфичную для реализации, и используя контейнер макроса внутри потока, все данные могут быть доступны.

Простое описание о работе

worqueue - это обработка прерываний нижнего половинного механика, где часть работы передается потоку ядра для последующего выполнения с preemtion при разрешении прерываний. Событие потока percpu/n создается ядром, потоки также могут быть созданы с помощью кода драйверов. Структура используется для идентификации потока, важным параметром внутри структуры является поле имени. Оно также содержит структуру на процессор, которая, в свою очередь, содержит головку waitqueue, на которую ожидает поток, и список ссылок, чтобы добавить структуру, которая определяет работу, то есть функцию и данные. Рабочий поток получает эту структуру в качестве входного параметра. Поток запускается и ждет момента ожидания для кого-то пробудить поток. Создана структура работы, определяющая функцию. Когда workqueue - это расписание, структура добавляется в хвост списка ссылок, и рабочий поток разбуждается. При пробуждении рабочий поток проходит через список ссылок, определенный в структуре каждого процессора, и начинает выполнять функции, определенные с помощью рабочей структуры в качестве параметра. После его выполнения удаляется запись из списка ссылок.