LINUX.ORG.RU

Шедулинг в linux.


0

1

Почему основной поток начинает выполняться раньше дочернего?

void new_thread(void *data)
 {
    printk("-----------------------------------------------\n");
    printk("I am new_thread, my pid is %d\n",current->pid);
    return;
 }

 static int __init
 main_func(void)
 {
    kernel_thread(new_thread,0,0);
    unsigned long i = 0;
    for(i; i<1000; i++)
             schedule();
    printk("------------------------------------------------\n");
    printk("I am main thread, my pid is %d", current->pid);
    return 0;
 }
insmod $name
 dmesg|tail

 ------------------------------------------------
 I am main thread, my pid is 5019
 ------------------------------------------------
 I am new_thread, my pid is 5020
Это магия?

оно наверняка буферизируется, так что очерёдность вывода не говорит об очерёдности выполнения.

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

оно наверняка буферизируется

Даже если и так, разве выводимая первым потоком не должна оказаться в буфере раньше(и соотвественно раньше показаться на терминале)? Можете дать ссылку на матчасть, если я не прав?

Rorschach
() автор топика
Ответ на: комментарий от visual

тогда поставь ещё флаш поле принта

C этим у меня затруднения ;] Как это сделать в случае с printk, учитывая что работает с модулем ядра и вывод происходит не в стандартный поток, а какой-то файл?

Rorschach
() автор топика

Короче, просто так вызывать шедуле не прокатит. Смотри schedule.c в качестве разных вариантов использования.

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

Черт, это было слишком коротко :/ Саму функцию schedule я уже затер до дыр, и вроде ничего криминального, из-за чего мне могли бы отказать в переключении текущей задачи, я там не нашел. Плюс во всех книжецах по ядру linux пишут, что дочерний процесс таки должен запускаться раньше родительского. В любом случае еще раз тщательно просмотрю код из schedule.c Спасибо.

Rorschach
() автор топика

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

gh0stwizard ★★★★★
()

Почему основной поток начинает выполняться раньше дочернего?

элементарно Ватсон - потому, что он основной

shty ★★★★★
()

Rorschach

I am main thread, my pid is 5019
------------------------------------------------
I am new_thread, my pid is 5020

Это магия?

и где тут магия? Почему должно быть по другому? Почему сначала мама учится говорить, а потом её дочка?

drBatty ★★
()

Никакая это не магия. Основной поток создан до создания нового, так как новый поток создаётся из основного.

post-factum ★★★★★
()
Ответ на: комментарий от shty

элементарно Ватсон - потому, что он основной
Почему должно быть по другому?
Основной поток создан до создания нового, так как новый поток создаётся из основного.

Стоп! Вы вообще о чем? Разумеется основной поток создается первым, но новый поток то создается до вывода текста функций printk! К тому же до вывода основной поток тысячу раз пропускает свою очередь на выполнение. Логично предположить, что за это время новый поток успеет отработать.

Проверить просто - смести вывод текста из мейна выше цикла.

Не пойму смысла этой перестановки, но результат конечно будет аналогичным.

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

Если хотите получить гарантированно определённые результаты при многопоточном программировании - пользуйтесь мьютексами, семафорами и т.п. Шаманство с циклами и задержками будет зависеть от погоды на Марсе

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

Дело не в результате. Я не могу понять почему оно работает так, это не дает мне спокойно спать.

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

обавь в вывод таймштамп, чтобы точно узнать очередность

Сделал. Основной поток вызывает printk первым. Значит дело не в буферизации.

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

Вы вообще о чем? Разумеется основной поток создается первым, но новый поток то создается до вывода текста функций printk!

так, намекну слегка - что происходит когда создаётся поток?

К тому же до вывода основной поток тысячу раз пропускает свою очередь на выполнение.

а это ничего, что стратегии планирования могут быть разными?

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

так, намекну слегка - что происходит когда создаётся поток?

Вызывается тот же do_fork с флагами CLONE_VM|CLONE_UNTRACED. Далее, если не вдаваться в подробности копируется родительская task_struct, некоторые поля изменяются и управление передается(должно передаваться, смотрите wake_up_new_task) НОВОЙ задаче. Но что-то здесь не так. Намек ваш не понял ;[ Нельзя сказать прямо в лоб?

а это ничего, что стратегии планирования могут быть разными?

Вроде нет. schedule() вполне себе задокументированная функция и должна передавать управление другому процессу в независимости от стратегии планирования. Я не прав?

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

Намек ваш не понял ;[ Нельзя сказать прямо в лоб?

поток помещается в очередь согласно своему приоритету

schedule() вполне себе задокументированная функция и должна передавать управление другому процессу в независимости от стратегии планирования.

дык, а теперь - какие бывают стратегии планирования?

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

поток помещается в очередь согласно своему приоритету

Точно. Моя ошибка. wake_up_new_task всего-лишь помещает процесс в runqueue.

дык, а теперь - какие бывают стратегии планирования?

FIFO и round-robin?

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

получается при RR планировании отказаться от своего кванта времени нельзя?

не, там всё немного не так работает - есть RR и FIFO, при RR таск берётся на выполнение, и по окончании кванта времени - ставится в конец очереди, а при FIFO - в начало, собственно вот практически и всё на что стратегия влияет

в общем стратегия планирования на отказ от кванта времени никак не влияет

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

при RR таск берётся на выполнение, и по окончании кванта времени - ставится в конец очереди, а при FIFO - в начало

При round-robin таски не двигаются в очереди, а стоят шеренгой по стойке смирно, а шедулер важно прохаживается вдоль строя и вызывает то одну то другую задачу.

При FIFO элемент помещаемый в очередь элемент ставится в конец очереди. В начало очереди он ставится при LIFO.

Топик стартера не понял. Пишут что schedule() - это «The main scheduler function. Schedules the highest priority task for execution.» Где говорится о том, что управление будет передано _другому_ таску?

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

При round-robin таски не двигаются в очереди, а стоят шеренгой по стойке смирно, а шедулер важно прохаживается вдоль строя и вызывает то одну то другую задачу.

ну как оно там «под капотом» реализовано - это я не знаю, но тому что я написал это не противоречит ( в том смысле что очерёдность вызовов будет ровно такая же)

При FIFO элемент помещаемый в очередь элемент ставится в конец очереди.

читайте внимательнее, конечно помещаемый в очередь элемент ставится в конец, но работающая таска, когда у неё заканчивается квант времени - ставится в начало очереди

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