|
|||||||
14. Планирование задач
Время создания: 20.09.2022 09:55
Текстовые метки: linux, ядро, модуль, программирование, язык, C, Си, пособие, документация
Раздел: Компьютер - Linux - Ядро - Пособие по программированию модулей ядра Linux
Запись: xintrea/mytetra_syncro/master/base/16636569150smwuiundy/text.html на raw.github.com
|
|||||||
|
|||||||
14. Планирование задач Есть два основных способа выполнения задач: тасклеты и очереди заданий. Тасклеты – это быстрый и простой способ планирования выполнения одной функции, например, при ее активации прерыванием. А вот очереди заданий хоть и более сложны, но зато лучше подходят для выполнения последовательностей задач. ▍ 14.1 ТасклетыНиже показан пример модуля тасклета. Функция tasklet_fn выполняется несколько секунд. При этом выполнение функции example_tasklet_init может продолжаться до точки выхода, что будет зависеть от того, была ли она прервана softirq. example_tasklet.c /* * example_tasklet.c */ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h>
/* Макрос DECLARE_TASKLET_OLD присутствует для совместимости. * См. https://lwn.net/Articles/830964/. */ #ifndef DECLARE_TASKLET_OLD #define DECLARE_TASKLET_OLD(arg1, arg2) DECLARE_TASKLET(arg1, arg2, 0L) #endif
static void tasklet_fn(unsigned long data) { pr_info("Example tasklet starts\n"); mdelay(5000); pr_info("Example tasklet ends\n"); }
static DECLARE_TASKLET_OLD(mytask, tasklet_fn);
static int example_tasklet_init(void) { pr_info("tasklet example init\n"); tasklet_schedule(&mytask); mdelay(200); pr_info("Example tasklet init continues...\n"); return 0; }
static void example_tasklet_exit(void) { pr_info("tasklet example exit\n"); tasklet_kill(&mytask); }
module_init(example_tasklet_init); module_exit(example_tasklet_exit);
MODULE_DESCRIPTION("Tasklet example"); MODULE_LICENSE("GPL"); После загрузки этого примера dmesg должна отобразить следующее: tasklet example init Example tasklet starts Example tasklet init continues... Example tasklet ends И хотя использовать тасклеты легко, они имеют несколько недостатков, и в среде разработчиков обсуждается их возможное исключение из ядра. Обратный вызов тасклета выполняется в атомарном контексте внутри программного прерывания, то есть он не может входить в режим ожидания или получать доступ к данным пользовательского пространства, в результате чего в обработчике тасклетов не получится выполнить всю работу. Кроме того, ядро разрешает одновременно выполнять только один экземпляр любого конкретного тасклета. При этом несколько разных могут выполняться параллельно. В последних версиях ядра появилась возможность заменить тасклеты очередями заданий, таймерами или прерываниями, выносимыми в отдельные потоки (threaded interrupts). Пока удаление тасклетов продолжает оставаться долгосрочной целью, в своем текущем виде ядро содержит более сотни случаев их использования. Сейчас разработчики продолжают вносить изменения в API, и для совместимости существует макрос DECLARE_TASKLET_OLD. Подробнее читайте на странице https://lwn.net/Articles/830964/. ▍ 14.2 Очереди заданийДобавлять задачи в планировщик можно через очередь заданий. Для выполнения прописанных в этой очереди задач ядро использует Completely Fair Scheduler (CFS). sched.c /* * sched.c */ #include <linux/init.h> #include <linux/module.h> #include <linux/workqueue.h>
static struct workqueue_struct *queue = NULL; static struct work_struct work;
static void work_handler(struct work_struct *data) { pr_info("work handler function.\n"); }
static int __init sched_init(void) { queue = alloc_workqueue("HELLOWORLD", WQ_UNBOUND, 1); INIT_WORK(&work, work_handler); schedule_work(&work); return 0; }
static void __exit sched_exit(void) { destroy_workqueue(queue); }
module_init(sched_init); module_exit(sched_exit);
MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Workqueue example"); |
|||||||
Так же в этом разделе:
|
|||||||
|
|||||||
|