Как работает таймер ЦП, если значение счетчика больше, чем оно может вместить? - PullRequest
2 голосов
/ 08 июля 2020

Если я не ошибаюсь, функция C sleep - это одно из мест, где используется таймер ЦП. Linux установит таймер и удалит процесс из scheduler. Таймер считает down, и как только он достигает 0, он прерывает работу ЦП, а ОС повторно добавляет процесс в планировщик. Я прав в этом?

Если да, то что произойдет, если значение таймера больше, чем количество бит, которое может обработать аппаратное обеспечение счетчика? Допустим, счетчик имеет максимум 23 бит, и мне нужно 24 битовое значение (т.е. мне нужно sleep в течение длительного времени).

Изменить:

Также , что, если у нас происходит несколько спящих одновременно, больше, чем у ЦП есть счетчики?

Ответы [ 2 ]

1 голос
/ 08 июля 2020

функция сна - одно из мест, где используется таймер ЦП

Нет. Ядро Linux реализует планировщик . Когда вы вызываете nanosleep() (библиотека GNU C на Linux использует nanosleep() для реализации sleep()), вы выполняете nanosleep syscall ; это заставляет ядро ​​не планировать эту задачу (обычно поток в процессе пользовательского пространства) до того, как истечет желаемая продолжительность, или сигнал доставляется обработчику сигнала пользовательского пространства, установленному без флага SA_RESTART, с использованием этой задачи (в этом случае системный вызов возвращается с -EINTR).

На микроконтроллере, скажем, Arduino или аналогичном, вы можете реализовать спящий режим, используя таймер.

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

/* Timer-based sleep function; returns the number of units slept,
   at most 'units'.  Can only sleep between 1 and TIMER_MAX, inclusive. */
static unsigned short  timer_sleep(unsigned short units);

void sleep(unsigned long duration)
{
    /* "long" sleep(s) */
    while (duration >= TIMER_MAX)
        duration -= timer_sleep(TIMER_MAX);

    /* "short" sleep(s) */
    while (duration > 0)
        duration -= timer_sleep(duration);
}

Вы можете заменить последнее, а l oop на timer_sleep(duration), если timer_sleep(u) всегда возвращает u. Написано, как указано выше, с использованием двух циклов while, сон будет работать до тех пор, пока timer_sleep(u) вернет u или меньше.

0 голосов
/ 08 июля 2020

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

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

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

...