С++ - как работают Sleep() и cin?

Просто любопытно. Как работает функция Sleep() (объявленная в windows.h)? Может быть, не только эта реализация, но и все. Что я имею в виду - как это реализовано? Как это сделать код "остановить" в течение определенного времени? Также любопытно, как cin → и те действительно работают. Что они делают точно?

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

Ответ 1

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

несколько раз в секунду компьютерные аппаратные часы прерывают CPU, что заставляет планировщик ОС активироваться. Затем планировщик просмотрит все процессы, которые пытаются запустить, и решает, какой из них запускается для следующего фрагмента времени.

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

Чаще всего, большинство процессов будут находиться в состоянии ожидания. Например, если процесс ожидает ввода с консоли, ОС может посмотреть информацию о процессах и посмотреть, к каким io-портам их ждет. Он может проверить эти порты, чтобы узнать, есть ли у них какие-либо данные для процесса. Если они это сделают, он может снова запустить процесс, но если данных нет, то этот процесс будет пропущен для текущего тайм-листа.

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

Поскольку ОС только возобновляет процессы после того, как что-то заставляет ее упредить выполняемый процесс, например, о выходе процесса или о прерывании аппаратного таймера, о котором я упоминал, sleep() не очень точен, насколько точно зависит от ОС или оборудования, но это обычно порядка одного или нескольких миллисекунд.

Если требуется больше точности или очень короткое ожидание, единственная опция - использовать описанную вами конструкцию цикла занятости.

Ответ 2

Операционная система планирует, как выполняются процессы (какие процессы имеют право запускать, в каком порядке,...). Sleep(), вероятно, выдает системный вызов, который сообщает ядру "не позволяйте мне использовать процессор за миллисекунды".

Ответ 3

Короче говоря, Sleep() сообщает ОС игнорировать процесс/поток на некоторое время.

Ответ 4

'cin' использует тонну перегруженных операторов. " → ", который обычно является правильным смещением бит, перегружен почти для каждого типа правого операнда в С++. Для каждой из них предусмотрена отдельная функция, которая считывает с консоли и преобразует вход в любой тип переменной, который вы указали. Например:

std::cin::operator>> (int &rhs);

Это не настоящий С++ - я не работал с потоками и перегрузкой через некоторое время, поэтому не помню тип возврата или точный порядок аргументов. Тем не менее, эта функция вызывается, когда вы запускаете cin → целочисленную переменную.

Точная базовая реализация зависит от операционной системы.

Ответ 5

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

Ответ 6

Если вы ищете более контролируемый способ блокировки потока/процесса в многопоточной программе, посмотрите на Семафоры, Мьютексы, Критические разделы и События. Это все методы, используемые для блокирования процесса или потока (без загрузки процессора через конструкцию while).

Они по сути работают от идиомы Wait/Signal, где заблокирован поток, и другой процесс сигнализирует об этом, чтобы он начал снова запускать. Эти (по крайней мере, в окнах) также могут иметь тайм-ауты, что обеспечивает аналогичную функциональность для Sleep().

Ответ 7

На низком уровне система имеет подпрограмму, называемую "планировщик", которая отправляет инструкции из всех запущенных программ в CPU (ы), которые фактически запускают их. Системные вызовы, такие как "Сон" и "Услышать", соответствуют инструкциям, которые сообщают планировщику IGNORE об этом потоке или процессе в течение фиксированного периода времени.

Как и для потоков С++, "cin" скрывает фактический дескриптор файла (stdin и stdout на самом деле являются такими ручками), к которым вы обращаетесь, и оператор " → " для него скрывает базовые вызовы для чтения и записи. С его интерфейсом реализация может быть специфичной для ОС, но концептуально она все еще делает такие вещи, как printf и scanf под капотом.