C ++ - как работают Sleep() и cin?
-
22-08-2019 - |
Вопрос
Просто любопытно.Как на самом деле работает функция Sleep() (объявленная в windows.h)?Может быть, не только эта реализация, но и любой другой.Под этим я подразумеваю - как это реализовано?Как это может заставить код "остановиться" на определенное время?Также любопытно, как cin >> и те, кто на самом деле работа.Что именно они делают?
Единственный известный мне способ "заблокировать" продолжение выполнения чего-либо - это цикл while , но, учитывая, что это требует огромной вычислительной мощности по сравнению с тем, что происходит, когда вы вызываете методы для чтения из stdin (просто сравните while (true) с чтением из stdin), я предполагаю, что это не то, что они делают.
Решение
Операционная система использует механизм, называемый планировщиком, чтобы все потоки или процессы, которыми она управляет, вели себя нормально вместе.
несколько раз в секунду аппаратные часы компьютера прерывают работу центрального процессора, что приводит к активации планировщика операционной системы.Затем планировщик просматривает все процессы, которые пытаются запуститься, и решает, какой из них будет запущен в следующий временной интервал.
Различные вещи, которые он использует для принятия решений, зависят от состояния каждого процесса и от того, сколько времени у него было до этого.Таким образом, если текущий процесс интенсивно использует центральный процессор, препятствуя прогрессу других процессов, это заставит текущий процесс подождать и переключится на другой процесс, чтобы он мог выполнить некоторую работу.
Однако чаще всего большинство процессов будут находиться в состоянии ожидания.Например, если процесс ожидает ввода данных с консоли, операционная система может просмотреть информацию о процессах и увидеть, какие порты ввода-вывода он ожидает.Он может проверить эти порты, чтобы увидеть, есть ли в них какие-либо данные для работы процесса.Если они это сделают, он может запустить процесс снова, но если данных нет, то этот процесс будет пропущен для текущего временного интервала.
что касается sleep()
, любой процесс может уведомить операционную систему о том, что он хотел бы немного подождать.Затем планировщик будет активирован еще до аппаратного прерывания (что также происходит, когда процесс пытается выполнить блокирующее чтение из потока, в котором нет данных, готовых к чтению), и ОС запишет, чего ожидает процесс.Переходя в спящий режим, процесс ожидает срабатывания будильника или может просто повторяться при каждом перезапуске до тех пор, пока таймер не истечет.
Поскольку ОС возобновляет процессы только после того, как что-то заставляет ее прерывать запущенный процесс, например, завершение процесса или аппаратное прерывание таймера, о котором я упоминал, sleep()
не очень точный, насколько точный, зависит от операционной системы или аппаратного обеспечения, но обычно это порядка одной или нескольких миллисекунд.
Если требуется большая точность или очень короткое ожидание, единственный вариант - использовать упомянутую вами конструкцию цикла занятости.
Другие советы
Операционная система планирует, как выполняются процессы (какие процессы могут выполняться, в каком порядке, ...).Sleep()
вероятно, выдает системный вызов, который сообщает ядру “не разрешайте мне использовать процессор для x миллисекунды”.
Короче говоря, Sleep() сообщает операционной системе некоторое время игнорировать процесс / поток.
"cin" использует тонну перегруженных операторов.'>>', который обычно имеет битовый сдвиг вправо, перегружен практически для каждого типа правостороннего операнда в C ++.Для каждого из них предусмотрена отдельная функция, которая считывает данные с консоли и преобразует входные данные в тот тип переменной, который вы указали.Например:
std::cin::operator>> (int &rhs);
Это не настоящий C ++ — я давно не работал с потоками и перегрузкой, поэтому не помню возвращаемый тип или точный порядок аргументов.Тем не менее, эта функция вызывается, когда вы запускаете cin >> целочисленную переменную.
Точная базовая реализация зависит от операционной системы.
Ответ зависит от операционной системы, но, вообще говоря, операционная система либо планирует запуск какого-то другого кода в другом месте в другом потоке, либо, если ей буквально нечего делать, она заставляет центральный процессор ждать, пока не произойдет аппаратное событие, которое заставляет центральный процессор перейти к некоторому коду, называемому обработчиком прерываний, который затем может решить, какой код запускать.
Если вы ищете более контролируемый способ блокировки потока / процесса в многопоточной программе, взгляните на семафоры, мьютексы, критические разделы и события.Все эти методы используются для блокировки процесса или потока (без загрузки процессора с помощью конструкции while).
По сути, они работают на основе идиомы Ожидания / сигнала, когда заблокированный поток ожидает, а другой процесс сигнализирует ему о повторном запуске.Они (по крайней мере, в Windows) также могут иметь тайм-ауты, обеспечивая тем самым функциональность, аналогичную Sleep().
На низком уровне в системе есть процедура, называемая "планировщик", которая отправляет инструкции от всех запущенных программ центральному процессору (ЦП), который фактически их запускает.Системные вызовы, такие как "Sleep" и "usleep", соответствуют инструкциям, которые предписывают планировщику ИГНОРИРОВАТЬ этот поток или процесс в течение фиксированного промежутка времени.
Что касается потоков C ++, "cin" скрывает фактический дескриптор файла (stdin и stdout на самом деле являются такими дескрипторами), к которому вы обращаетесь, а оператор ">>" для него скрывает базовые вызовы для чтения и записи.Поскольку это интерфейс, реализация может зависеть от операционной системы, но концептуально он по-прежнему выполняет такие вещи, как printf и scanf под капотом.