LINUX.ORG.RU

[kernel][thread] Создание постоянно работающего потока ядра


0

2

Всем доброго времени суток!
Необходимо создать поток ядра, который бы работал постоянно.
То есть после прерывания его планировщиком и отработки какой-то другой задачи он оставался в очереди на выполнение.

Сейчас скопировал работу pdflush. Получился примерно такой код:

[code=с]
for(;;) {
printk(«1\n»);
set_current_state(TASK_INTERRUPTIBLE);
schedule();
printk(«2\n»);
}
[/code]

После первого запуска потока появляется сообщение «1». После поток останавливается навсегда.

Пробовал вместо TASK_INTERRUPTIBLE устанавливать TASK_RUNNING. Тогда выполняется только мой поток - загрузка на этом заканчивается насовсем.

pdflush будится постоянно wake_up_process() по таймеру в 1 секунду. Но для моей задачи это слишком много. Нельзя ли как-то всегда оставаться в очереди на выполнение.

PS: надеюсь здесь бывают специалисты по таким вопросам


может тебе это поможет? но не уверен, будет ли это работать в отдельном потоке.

#include <linux/timer.h>
struct timer_list {
        /* ... */
        unsigned long expires;
        void (*function)(unsigned long);
        unsigned long data;
};

void init_timer(struct timer_list *timer);
struct timer_list TIMER_INITIALIZER(_function, _expires, _data);

void add_timer(struct timer_list * timer);
int del_timer(struct timer_list * timer);

nanoo_linux ()

А что он делает-то? Я бы сначала попробовал просто не делать никаких лишних телодвижений.

const86 ★★★★★ ()

По-моему задача поставлена неверно.

Если поток должен обработать какое-то событие, нужно дать ему RT-приоритет и останавливать его на мьютексе (или другом средстве синхронизации) в ожидании нужного события. А так, чтобы поток работал постоянно... ты считаешь что ли что-то? Почему тогда в ядре?

annoynimous ★★★★★ ()
while(!kthread_should_stop()) {
...
...
    schedule_timeout_interruptible(HZ / 100);
}

будет просыпаться от планировщика 100 в секунду

anonymous ()

Потоку не нужно следить за какими-то событиями, он сам будет событием (если это можно так назвать) для других процессов.
Я ПОНИМАЮ и ОСОЗНАЮ, что в реальной жизни это ПОЧТИ бессмысленно, но так хочет заказчик :)

Спасибо, попробую со срабатыванием 100 раз в секунду, но это всё равно не совсем подходит.
Курил умную книжку по ядру, но так и не понял:
почему пользовательская задача выбирается из очереди на выполнение и работает отведённое ей время,
а мой поток из состояние TASK_RUNNING нельзя прервать по исчерпанию кванта времени и запустить потом заново?

dickest ()
Ответ на: комментарий от dickest

> а мой поток из состояние TASK_RUNNING нельзя прервать

по исчерпанию кванта времени


да можно. если, конечно, CONFIG_PREEMPT.

планировщику вообще все равно, в этом смысле
kernel thread ничем не отлисается.

а вызывать schedule() в состоянии TASK_RUNNING
бессмысленно. на какой эффект вы рассчитываете?

idle ★★★★★ ()
Ответ на: комментарий от dickest

>Я ПОНИМАЮ и ОСОЗНАЮ, что в реальной жизни это ПОЧТИ бессмысленно, но так хочет заказчик :)

Ты бы описал нормально что нужно, а для заказчика можно и пустой поток создать который ничего не делает :) В списке процессов увидит и успокоится. Создание своих потоков ядра вообще не приветствуется.

anonymous ()
Ответ на: комментарий от Boy_from_Jungle

Поток должен грузить систему, чем больше тем лучше. Это эксперимент такой :)

книжка Daniel P. Bovet, Marco Cesati «Understanding the Linux Kernel»

dickest ()
Ответ на: комментарий от annoynimous

вопрос только в том почему поток нужно приостанавливать:
set_current_state(TASK_INTERRUPTIBLE);
а с другой стороны почему после приостановки он сам не возобновляется

dickest ()
Ответ на: комментарий от dickest

может потому что на момент запуска вашего потока шедулер еще непроинициализирован, вы из загружаемого модуля поток стартуете или залезли в ядро?

ACR ()
Ответ на: комментарий от dickest

> почему поток нужно приостанавливать:

смотря для чего. для того, чобы выполнялись другие
процессы - не нужно (еще раз, при CONFIG_PREEMPT).

а с другой стороны почему после приостановки он сам

не возобновляется



это все равно, что удивляться тому, что программа перестает
работать после exit() ;)

он и не должен «возобновляется», он же не running.
вы же сами выставили ->state = TASK_INTERRUPTIBLE.

Поток должен грузить систему, чем больше тем лучше.

Это эксперимент такой :)



хм. и зачем это делать в kernel space?

idle ★★★★★ ()
Ответ на: комментарий от idle

если я правильно понял, то CONFIG_PREEMPT - это опция «Использовать вытеснение задач»?

по-моему, она у меня включена...
и если я не приостанавливаю поток, то только он и работает:

for(;;) {
printk(«1\n»);
set_current_state(TASK_RUNNING);
schedule();
printk(«2\n»);
}

dickest ()
Ответ на: комментарий от dickest

> и если я не приостанавливаю поток, то только он и работает:

и как вы об этом узнали?

set_current_state(TASK_RUNNING);

schedule();



еще раз повторяю, нет никакого смысла вызывать schedule()
в состоянии TASK_RUNNING. это, практически, nop.

idle ★★★★★ ()
Ответ на: комментарий от dickest

> но почему тогда из состояния TASK_RUNNING

поток не выходит по окончанию кванта времени?


уфф ;)

что значит «не выходит» ? не меняется его
->state == TASK_RUNNING ? он и не должен.
он же running! даже если он вытеснен другой
задачей, он все равно runnable.

idle ★★★★★ ()
Ответ на: комментарий от idle

Всем спасибо, в особенности idle и ACR!

Сделал так:
- запуск потока при инициализации ядра
- в потоке сразу его тормозим (TASK_INTERRUPTIBLE + schedule)
- по таймеру с большой задержкой (15 секунд от начал загрузки) будим
- поток входит в бесконечный цикл и там сидит пока не остановят

dickest ()
Ответ на: комментарий от dickest

я так и не понял, зачем это все.

Сделал так:


в любом случае, это намного сложнее, чем необходимо.

idle ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.