LINUX.ORG.RU

Что такое kernel preemption ?


0

0

Ядро 2.6
Правильно ли я понимаю :
когда шедулятор собирается переключить в очереди текущий процесс ,
он может этого не сделать и оставить текущий процесс текущим
Именно это называется kernel preemption ?

★★★★★

Не правильно.
kernel preemption это снятие процесса с выполнения (переключение процесса) в момент когда он выполняется в режиме ядра.

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

т.е. в тот момент , когда он делает системный вызов либо в момент срабатывания прерывания ?

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

Речь идет о следующем куске кода ядра :

switch_count = &prev->nivcsw;
if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
switch_count = &prev->nvcsw;
if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&
unlikely(signal_pending(prev))))
prev->state = TASK_RUNNING;
else
deactivate_task(prev, rq);
}

Идет проверка статуса процесса
Что означает :
if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {

kto_tama ★★★★★
() автор топика

NO preempt:

При входе в сисколл прерывания выключены, во время выполнения сисколла никно (практичеки) не может прервать ядро.Т.е.если сисколл выполняется долго, то система "подвисает".

preempt:

После входв сисколл насильно включаем прерывания, и код ядра (из сисколла) выполняется как процесс.т.е. если сделать for(;;); в сисколле, ядро не повиснет, процесс будет в D state.

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

preempt - эту опцию вообще можно выставить при сборке ядра ?
Речь идет о файле :
Kernel 2.6.9/kernel/sched.c
строка 2687

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

>!(preempt_count() & PREEMPT_ACTIVE)

Верно если не в preempt.

> prev->state

ищи *.h файл где описаны состояния процессов.

schedule() может быть вызван из сисколла.Там видимо есть проверка, в preempt мы или нет.

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

> NO preempt:

> При входе в сисколл прерывания выключены,

Больше никогда никому такого не говори, ибо это не так.

> во время выполнения сисколла никно (практичеки) не может прервать ядро.Т.е.если сисколл выполняется долго, то система "подвисает".

Сильно зависит от code path, которую выполняет сискол

> preempt:

> После входв сисколл насильно включаем прерывания

Нет. Прерывания включены практически всегда - их запрещают только драйверы (сейчас - очень редко), низкоуровневый код ядра (очень редко) и любой код, выполняющийся в NO_PREEMPT под спинлоком.

> и код ядра (из сисколла) выполняется как процесс

Сискол _всегда_ выполняется от имени процесса

> .т.е. если сделать for(;;); в сисколле, ядро не повиснет, процесс будет в D state.

Не уверен насчет D - может, R ?

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

> preempt - эту опцию вообще можно выставить при сборке ядра ?

При конфигурации ядра.

В том куске, о котором ты спрашивал, делается проверка, не выключен ли preempt, и, если не выключен, текущий процесс может быть снят с процессора (если ему не надо обработать сигнал).

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

>Больше никогда никому такого не говори, ибо это не так.

Для i386 так. sysenter disables interrupts.

>Сильно зависит от code path, которую выполняет сискол

имелся в виду сразу после входа в ring0.

>Нет. Прерывания включены практически всегда

ENTRY(sysenter_entry)
        movl TSS_sysenter_esp0(%esp),%esp
sysenter_past_esp:
        sti
        ^^^ ;)

>Сискол _всегда_ выполняется от имени процесса

от имени и как - разные вещи.

>Не уверен насчет D - может, R ?

насчет D сам не уверен также как и на счет R.

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

>>Нет. Прерывания включены практически всегда

>ENTRY(sysenter_entry)
> movl TSS_sysenter_esp0(%esp),%esp
>sysenter_past_esp:
> sti
> ^^^ ;)

Поэтому я и сказал "практически". На короткую последовательность команд
входа в ядро они и в самом деле запрещены. Потом разрешаются (причем
как раз той инструкцией, на которую ты указал).

Цитата оттуда же:
/*
* No need to follow this irqs on/off section: the syscall
* disabled irqs and here we enable it straight after entry:
*/

>>Сискол _всегда_ выполняется от имени процесса

>от имени и как - разные вещи.

В чем разница?

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

кстати в 2.4 ядре они не включаются после sysenter.

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

>В чем разница?

от имени -> только та же page directory.

как -> может быть прерван по таймеру, его состояние сохранено и т.д.

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

> кстати в 2.4 ядре они не включаются после sysenter.

Они всегда включаются после входа в ядро, поверь мне :)

>>В чем разница?

>от имени -> только та же page directory.

>как -> может быть прерван по таймеру, его состояние сохранено и т.д.

Не понял. Слишком умно для меня :/

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

Вот по поводу разницы - нельзя ли поподробнее?

Для наглядности предлагаю пример (как я себе это представляю): прога (userspace) выполняет системный вызов например read() (какого-то девайса) -> идёт переход в kernel space -> [подготовка к выполнению read() драйвера] -> read() драйвера -> [подготовка к возврату в userspace]

Допустим в read() драйвер блокируется на время получения данных (переходит в состояние D).

Так где здесь "от имени" и "как"? А то есть подозрение, что я вас неправильно понял

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

> Допустим в read() драйвер блокируется на время получения данных (переходит в состояние D).

блокируется то не сам драйвер, блокируется вполне конкретный процесс затребовавший операцию чтения :)

// wbr

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

> Допустим в read() драйвер блокируется на время получения данных (переходит в состояние D).

Это хреновый драйвер :/ Нормальные делают wait_*_interruptible (состояние S).

Насчет "от имени" и "как" - зависит от определения процесса. Если это userspace сущность - то тогда "от имени". Если считаем, что процесс при выполнении системного вызова просто переходит в другой режим исполнения, то "как". Практически все (или даже все) системные вызовы выполняются от имени процесса.

Правда, что я должен ответить на твой пример - я не понял :)

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

>Это хреновый драйвер :/ Нормальные делают wait_*_interruptible (состояние S).

Хреновый? Это почему же? Конечно опыт у меня небольшой (в плане написания драйверов) - всего лишь около 2 лет пишу дрова для USB-устройств и что-то я довольно редко встречал в дровах явное оперирование состоянием. Зачем это нужно? USB-подсистема предоставляет определённый (и в большинстве случаев достаточный) интерфейс. Применительно к примеру - блокировка происходит в функции ожидающей поступления данных по USB-шине (состояние D) при их приходе состояние будет автоматически переведено в R.

BTW, в чём по вашему преимущества состояния S перед D с точки зрения ресурсопоглощения системы и времени реакции на переход S->R и D->R?

>Правда, что я должен ответить на твой пример - я не понял :)

Интересно узнать что вы понимаете под "переходит в другой режим исполнения"? Вы хотите сказать что возможна ситуация когда pgd не будет соответствовать процессу?

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

>Это хреновый драйвер :/ Нормальные делают wait_*_interruptible (состояние S).

Хреновый? Это почему же? Конечно опыт у меня небольшой (в плане написания драйверов) - всего лишь около 2 лет пишу дрова для USB-устройств и что-то я довольно редко встречал в дровах явное оперирование состоянием. Зачем это нужно? USB-подсистема предоставляет определённый (и в большинстве случаев достаточный) интерфейс. Применительно к примеру - блокировка происходит в функции ожидающей поступления данных по USB-шине (состояние D) при их приходе состояние будет автоматически переведено в R.

BTW, в чём по вашему преимущества состояния S перед D с точки зрения ресурсопоглощения системы и времени реакции на переход S->R и D->R?

>Правда, что я должен ответить на твой пример - я не понял :)

Интересно узнать что вы понимаете под "переходит в другой режим исполнения"? Вы хотите сказать что возможна ситуация когда pgd не будет соответствовать процессу?

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

Прошу прощения - два раза запостилось - с сетью у нас на работе ерунда какая-то...

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

>>Это хреновый драйвер :/ Нормальные делают wait_*_interruptible (состояние S).

> Хреновый? Это почему же?

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

> пишу дрова для USB-устройств

Ненавижу, бл#, подсистему USB в Linux. #баное глюкалово.

> что-то я довольно редко встречал в дровах явное оперирование состоянием.

причем здесь _явное_ оперирование состоянием? Просто используются функции, которые переводят процесс в uninterruptible sleep (то есть варианты wait_* без _interruptible).

> блокировка происходит в функции ожидающей поступления данных по USB-шине (состояние D) при их приходе состояние будет автоматически переведено в R

Вот поэтому - #баное глюкалово. Данные - они могут и не прийти. О таких вещах в Linux вообще мало думают, а в USB-подсистеме не думают вообще. Но зато крутой перец GregKH всех учит жить.

> Интересно узнать что вы понимаете под "переходит в другой режим исполнения"?

Переходит в режим ядра (фраза из старой книги Баха про Unix). А на pgd, pmd и и прочее я не заморачиваюсь.

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

По поводу D и S - накладные расходы (на реализацию вашего варианта) на мой взгляд перевешивают вероятность глючного железа. По большому счёту будет ли бессмертный процесс в userspace или он повиснет в каком-то обработчике ожидающем прихода данных - для системы это одинаково хреново (хотя во втором случае скорее всего будет занято меньше памяти - но от этого не легче).

По поводу глюкалово - могу не согласится - по крайней мере с 2.4 к 2.6 заметен серьёзный прогресс особенно в плане обработки ситуаций возникающих при передаче объёмов данных близких к пределу пропускной способности, хотя в целом до реализации того что описано в спецификации USB 2.0 конечно далековато... Интересно с какими глюками вам приходилось сталкиватся - любопытно?

BTW, в целом перевод в D не так уж фатален - например в нормальном драйвере при выдёргивании девайса (и процесс в D) ничего страшного не произойдёт - он будет переведён в R и будет возвращена ошибка получения данных. Хотя в целом можно и изобретать велосипед не пользуюясь стандартными интерфейсами - в ядре есть примеры таких драйверов (но они скорее исключение чем правило)

Кто такой GregKH? А то я самоучка - тёмный человек, не светский...

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

> По поводу D и S - накладные расходы (на реализацию вашего варианта) на мой взгляд перевешивают вероятность глючного железа.

Я плакал 8( Какие накладные расходы имеются в виду? Насчет "вероятности глючного железа" - какая такая вероятность? Глючное железо БУДЕТ, пиши драйвер, рассчитывая на это.

> будет ли бессмертный процесс в userspace или он повиснет в каком-то обработчике ожидающем прихода данных - для системы это одинаково хреново

Ты не читаешь, что я пишу. Да, не важно где завис процесс. Но если он в S, я делаю kill - и нет процесса! И нет проблемы, совсем.

> По поводу глюкалово - могу не согласится - по крайней мере с 2.4 к 2.6 заметен серьёзный прогресс

Да, заметен. Но мое мнение остается в силе.

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

Этот глюк с D-state (только я не уверен, что мне выдергивание кабеля помогает :) ). На 2.4 был вообще атас - вставляешь флэшку, монтируешь, работаешь, демонтируешь. Потом вставляешь _другую_ флэшку - и ядро говорит "no medium found".

> перевод в D не так уж фатален - например в нормальном драйвере при выдёргивании девайса (и процесс в D) ничего страшного не произойдёт - он будет переведён в R и будет возвращена ошибка получения данных.

Во-первых, не всегда возможно просто выдернуть. Во-вторых, какого черта я должен выдергивать кабель, возможно, прибивая этим другие процессы, если это чисто программная проблема? И в-третьих: такой подход по всему ядру, а некоторые устройства не выдергиваются :(

> Кто такой GregKH?

Он отвечал за USB в ядре 2.4 Теперь всех учит жить (и писать драйверы).

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

>Я плакал 8( Какие накладные расходы имеются в виду? Насчет "вероятности глючного железа" - какая такая вероятность? Глючное железо БУДЕТ, пиши драйвер, рассчитывая на это.

Что-то я не совсем понял (по поводу накладных расходов). Вы предлагаете (применительно к моему примеру) в read() драйвера сделать sleep interruptible до получения данных (и этот процесс S - те его можно при желании прихлопнуть) - хм, а кто тогда будет получать данные (которые могут как вы говорите не прийти никогда)?

Выдёргивание кабеля приведено к тому что сама подсистема usb достаточно неплохо отрабатывает все издевательства - другое дело если у человека который писал драйвер (а точнее драйвер верхнего уровня) руки растут не из того места...В usb дровах обычно при запросе выставляется timeout после истечения которого возвращается ошибка.

По поводу флешки - не знаю - ядро 2.4 сам не очень люблю - например там при превышении пропускной способности процесс действительно переводится в D а при освобождении ресурсов там и остаётся, в 2.6 такого нет. Функция регистрации usb девайса не блокируемая - может пройти время (секунды) на то чтобы система его (девайс) увидела - я с этим сталкивался когда сразу лил прошивку после регистрации (она то заливалась ok то не ok)

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

> Вы предлагаете (применительно к моему примеру) в read() драйвера сделать sleep interruptible до получения данных (и этот процесс S - те его можно при желании прихлопнуть) - хм, а кто тогда будет получать данные (которые могут как вы говорите не прийти никогда)?

Не совсем понимаю вопрос... С USB-драйверами незнаком, но обычный драйвер ждет не собственно данных, а прерывания, извещающего об их прибытии. Ждет он это прерывание в wait_event или wait_for_completion. Поскольку нормально написанный драйвер всегда допускает, что железка может заглючить/отказать, он ждет прерывания с тайм-аутом (wait_for_completion_timeout) и/или разрешая прервать ожидание сигналом (wait_for_completion_interruptible). Параноики типа меня ждут прерывания с разрешенными сигналами и тайм-аутом (wait_for_completion_interruptible_timeout). То есть - всего-то делов, вызвать нужную функцию (у wait_even тоже есть такие варианты, как у wait_for_completion) и отвалиться по коду возврата.

> у человека который писал драйвер (а точнее драйвер верхнего уровня) руки растут не из того места

Это был usb-storage, который (AFAIK) писал GregKH.

> лил прошивку

Я прошивки через libusb заливал. Вообще, при наличии libusb драйвер ядра часто можно не писать.

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

>Не совсем понимаю вопрос... С USB-драйверами незнаком, но обычный драйвер ждет не собственно данных, а прерывания, извещающего об их прибытии Это если нет альтернативы :-) В usb есть - зачем связываться с прерываниями и проч когда можно этого избежать? Низкоуровневыми вещами вроде возни с прерываниями занимается (в подсистеме usb) драйвер низкого уровня hcd, что хорошо соответствует тому что написано в спецификации USB 2.0. Он и предоставляет API который и должен использовать драйверо-писатель - как я уже говорил это здорово сокращает время разработки.

>Я прошивки через libusb заливал. Вообще, при наличии libusb драйвер ядра часто можно не писать. Иногда без заливки в драйвере не обойтись - скажем если прошивка льётся особым образом (заливается одна прошивка, инициализируется, заливается другая) - зависит от дизайна девайса

BTW, вот уж что глючное так это IMHO libusb :-)

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

>> прерывания, извещающего об их прибытии

> Это если нет альтернативы :-)

Посмотрел в учебнике: ну, в USB callback function - да никакой разницы с прерыванием. Что ты используешь в callback handler - wait_event? Или как-то более хитро?

> BTW, вот уж что глючное так это IMHO libusb :-)

Ну, не более, чем нижележащая подсистема 8)

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

>Посмотрел в учебнике: ну, в USB callback function - да никакой разницы с прерыванием.

Ну не совсем - это если вызов функции запрашивающей данные неблокируемый тогда будет похоже на работу с обработчиком прерывания. Я использую блокируемые ф-ции без callback'ов (callback'и - зло :-)) - идёт запрос на получение данных с такого-то ендпойнта с таймаутом - если что - ф-ция вернётся с ошибкой через таймаут или сразу. Как это реализовано на низком уровне (hcd) я не заморачивался - и без этого есть чем заняться :-). Теоретически конечно присутствует возможность если железка "сошла с ума" и каким-то образом подвесит код (hcd) который отвечает за побудку по таймауту - но это надо смотреть код - лично мне кажется что это очень маловероятно. По крайней мере в дровах (usb) я не встречал чтобы учитывалась такая ситуация - хорошо уже если скажем в mmap() проверяется не происходит ли выход за пределы маппируемого буфера...

В крайнем случае пользователь/watchdog перезагрузит систему и если это повторится - заменить железку а глючную спустить в унитаз конкурентам :-)

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

> идёт запрос на получение данных с такого-то ендпойнта с таймаутом

Если ты поставил тайм-аут и обрабатываешь его возможность, то к тебе претензий уже нет (скорее всего ;))

> присутствует возможность если железка "сошла с ума" и каким-то образом подвесит код (hcd) который отвечает за побудку по таймауту

Теоретически это возможно, но программными средствами от этого не защитишься. Правда, железке не нужно сходить с ума - если ты ей передашь DMA-адрес того самого кода hcd, то всё ;)

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

Как то мы слегка отклонились от темы вопроса - как было правильно было сказано выше kernel preemption - способность ядра вытеснять процесс/тред выполняющий код в ring 0 более важным процессом/тредом. Причём вытеснение AFAIK может произойти в любой точке выполняемого кода за исключением критических секций (для обычного ядра) а не только в определённых точках. В rt-патче Molgnar'а ещё круче - время реакции улучшается (заметно даже на глаз) за счёт накладных расходов (тоже заметны)

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

>Видео здесь ни при чем. Это халтурно небрежный стиль программирования, свойственный ядру :(.

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

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

>>Видео здесь ни при чем. Это халтурно небрежный стиль программирования, свойственный ядру :(.

>Ну скорее горе драйверописателям

GregKH - он не просто драверописатель. И usb-storage не "мужики с остановки" писали, а вполне себе core kernel hackers.

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

Ну не одной usb-подсистемой жив человек...

Никто не пробовал с прогой использующей в данный момент pci-девайс этот девайс "на лету" отключить? А потом ещё и подключить? :-) По идее Plug and Play - всё должно нормально отработать...

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

> Ну и в чём разница между "сунул и попер" и хотплагом?

"Да никакой разницы" -- (С) "Чужой-4: Воскрешение" 8)

Для hotplug на PCI нужна особая поддержка со стороны контроллера шины. На CompactPCI, например, такая есть.

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

Хм, c PCI я не особенно знаком, но тут говорят что обычно такая поддержка есть и при этом главное чтобы девайс должен предоставлять нужные данные - так? В ядре PCI PnP вроде экспериментал - просто интересно как реально сейчас с этим обстоят дела

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