Операционная система Реализация событий / сигналов / ручек ожидания - PullRequest
4 голосов
/ 19 июля 2010

Из любопытства мне было интересно, как в операционных системах реализованы потоки пробуждения, ожидающие события / дескрипторы и т. Д.

Например, скажем, поток ОС постоянно просматривает список дескрипторов ожидания и при необходимости выполняет соответствующие потоки. Не то чтобы я верил, что это реализовано так, как кажется, неэффективно.

Я думаю, что более вероятно, что ОС устанавливает аппаратные прерывания в области памяти, содержащей примитивы синхронизации, связанные с открытыми дескрипторами / событиями ожидания, и затем, когда они запускаются, он может планировать поток с осторожностью, чтобы не планировать его больше один раз?

EDIT

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

Ответы [ 3 ]

3 голосов
/ 19 июля 2010

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

Однако в основном это относится к управлению состоянием потока. Поток - это одно из нескольких разных состояний одновременно: спящий, готовый или работающий (обычно это больше, но это все, что нужно для целей этого обсуждения). Поток в рабочем состоянии на самом деле работает, и код в потоке выполняется. Поток в «спящем» состоянии не запущен, и планировщик пропустит его, когда решит, кто будет работать дальше. Поток в состоянии «готовности» в данный момент не выполняется, но как только другой поток переходит в спящий режим или его временной интервал истекает, планировщик может свободно планировать переход этого потока в состояние выполнения.

Таким образом, в основном, когда вы вызываете «wait» для объекта мьютекса, ОС проверяет, принадлежит ли объект уже другому потоку, и если да, устанавливает состояние текущего потока как «спящий», а также помечает поток как «ожидающий» на "этот конкретный мьютекс.

Когда поток, которому принадлежит мьютекс, завершен, ОС перебирает все ожидающие его потоки и устанавливает их в состояние «готов». В следующий раз, когда планировщик приходит в себя, он видит «готовый» поток и переводит его в «работающее» состояние. Поток запускается и проверяет, может ли он снова получить блокировку мьютекса. На этот раз никто не владеет им, поэтому он может продолжать свой веселый путь.

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

1 голос
/ 19 июля 2010

Ответ вводного учебника состоит в том, что, когда один поток спит в ожидании события, он попадает в очередь ожидающих потоков.Поток помечается как «ожидающий», поэтому планировщик процессов операционной системы пропускает поток, когда ищет объекты для запуска на процессоре.В конце концов (в правильной программе) другой поток разбудит один или все потоки, ожидающие в очереди событий.Затем потоки помечаются как «готовые», и ОС снова начинает их планировать.

Конечно, как это на самом деле реализовано, довольно сложно.Я думаю, что это ваш настоящий вопрос.Для Linux механизм, который вы ищете, называется futex , и они слишком сложны, чтобы я мог здесь отдать им должное.Если реклама Википедии вызвала у вас интерес, покопайтесь во внешних ссылках внизу страницы вики.

0 голосов
/ 19 июля 2010

Я считаю, что реализация проще, поток помещается в список ожидающих потоков (все потоки, ожидающие определенного события / handle / mutex / и т. Д. Когда пробуждается примитив синхронизации,все потоки переведены в рабочее состояние и список очищен.

...