LINUX.ORG.RU

Kernel, ожидания, вытеснение, LDD

 


0

3

Всем доброго времени суток!

Во время прочтения Linux Device Drivers (глава 6, «засыпания» при блокирующем вводе выводе) возникло небольшое непонимание. Приведен код, целью которого является помещение процесса в состояние сна до наступления определенного события (невыполнение условия сна):

while (spacefree(dev) == 0)
{
...
  prepare_to_wait(&dev->outq, &wait, TASK_INTERRUPTIBLE);
  if (spacefree(dev) == 0)
    schedule( );
  finish_wait(&dev->outq, &wait); 
...
}
Аналогичный код был найден в исходниках ядра (например, inet_connection_sock.c:inet_csk_wait_for_connect()). Но у меня возникает подозрение, что данный код не будет работать правильно в ядрах с вытеснением. Допустим, работа произошла по следующему сценарию: При входе в цикл условие истино - цикл начинается. После этого в другом потоке выколнения условие изменяется, пробуждаются все процессы, находящиеся в очереди outq (нашего там еще нет). Затем первый поток выполняет метод prepare_to_wait - процесс помещается в очередь, а его состояние - TASK_INTERRUPTIBLE, но процесс все еще на процессоре и, по идее, проверив условие засыпания должен пропустить вызов shedule и перейти в состояние TASK_RUNNING в методе finish_wait. Однако, до вызова finish_wait он может быть вытеснен другим процессом или прерыванием и отправиться в спячку непредсказуемой длительности при ложном значении условиия сна. Подскажите, правильно ли я понимаю эту ситуацию, и если нет, то куда копать для ее понимания.

Спасибо.

Однако, до вызова finish_wait он может быть вытеснен другим процессом или прерыванием и отправиться в спячку непредсказуемой длительности при ложном значении условиия сна.

spacefree() однажды перестанет возвращать 0, и никогда больше не будет его возвращать, я правильно понял?

schedule(), если я ничего не путаю, действительно, прервёт выполнение процесса и поместит его в очередь. То есть продолжится выполнение через некий, действительно неопределённый по длительности, период. Но он всё равно будет возвращён к выполнению. Т. к. Linux - не realtime OS, это считается нормальным. Если вам нужно мгновенное срабатывание, не делайте schedule(), делайте активное ожидание (но это займёт полностью одно ядро, если оно всего одно - работать не будет). Можно добавить использование семафора или иного доступного блокирующего механизма. Либо просто максимизируйте приоритет потока и используйте этот же самый код.

P. S. Давно интересуюсь разработкой в ядре, но не нахожу интересующей задачи. Топикстартер, если есть интересная/полезная задача, можешь со мной связаться, возможно, захочу поучаствовать.

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

(но это займёт полностью одно ядро, если оно всего одно - работать не будет)

Здесь я, наверное, неправ. Но всё равно этот вариант плохой.

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

Спасибо за разъяснения! Примерно такого поведения я и ожидал. Хотя была мысль запретить вытеснение перед prepare_to_wait и разрешить сразу после проверки условия - на всякий случай. А что можно почитать по типу LDD но более актуальное?

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

А что можно почитать по типу LDD но более актуальное?

Более актуального учебника по написанию драйверов нет, хотя на lwn.net была серия статей, дополняющая LDD3 материалами по более новым ядрам: http://lwn.net/Articles/2.6-kernel-api/

Если добавить к вышеприведенному R.Love «Linux Kernel Development (3rd Edition)», получится неплохой фундамент, _но_ копания в исходниках это не отменяет - развитие идет постоянно. Правда, именно драйверные интерфейсы последние годы меняются мало.

tailgunner ★★★★★ ()
Последнее исправление: tailgunner (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.