Баг RTC таймера - уход времени "вперёд" на мультипроцессорном ядре Windows XP Описание: При использовании Windows XP на современных ПК обнаружился глюк - системное время (RTC часы) уходит вперёд, причем степень ухода зависит от активности работы ПК и может составлять до 5 минут в день. Проблема проявляется только в Windows XP. На выключенном ПК, под UEFI/BIOS или в Windows 7 - время идет правильно. Часовая микросхема RTC должна быть независимой частью, но на современных материнских платах это не так. Исследование показало, что уход часов "вперед" происходит при постоянном переключении периода системного таймера 16 мс (15.625 мс) в 1 мс (0.977 мс) и обратно. В Windows XP (по умолчанию) этот таймер работает с периодом 16 мс и если на ПК не проявлять активности - то он продолжит работать с периодом 16 мс. Но при запуске Хрома или мультимедиа приложений, таймер переключается в режим работы с периодом 1 мс и может возвращаться на 16 мс. При жестко установленном периоде 16 мс (или 1 мс) время идет точно, но при постоянном переключении таймера 16 мс - 1 мс - 16 мс - 1 мс происходит сбой в работе часов реального времени RTC. Решение проблемы: Решение проблемы - утилита Timer_Fix.exe (с исходным кодом, написанная на Visual Studio 6.0). Программа не имеет интерфейса, после запуска она переведет системный таймер на период 1 мс и оставит его неизменным. Программа постоянно висит в процессах до перезагрузки ОС. Для завершения работы (в случае необходимости) нужно просто прибить процесс Timer_Fix.exe через "Диспетчер задач". Для удобства лучше положить Timer_Fix.exe в "Автозагрузку" и забыть о проблеме с уходом времени. В целом, данный фикс можно считать "костыльным", но ничего лучшего на данный момент нет. Программа для демонстрации проблемы (программа для накрутки времени): RTC_bug_demonstrations\Timer_v10\Timer_src_BCB6.0 - исходные коды программы RTC_bug_demonstrations\Timer_v10\timeBeginPeriod.exe RTC_bug_demonstrations\Timer_v10\timer.exe Разработчик программы - женщина-программист Xenia. Огромное ей спасибо! Данная программа служит для наглядной демонстрации проблемы с RTC таймером. Она устанавливает период системного таймера 1 мс (0.977 мс) выдерживает 0.2 секунды, устанавливает 16 мс (15.625 мс) выдерживает 0.2 секунды и далее продолжает переключать системный таймер с заданными длительностями. Программа состоит из 2-х частей: 1. timeBeginPeriod.exe - консольная программа для установки режима таймера. Заданный режим (период и длительность) передаётся в параметрах командной строки. Программа представлена с исходным кодом на Borland C++ Builder 6.0. 2. timer.exe - это GUI интерфейс для timeBeginPeriod.exe. В графическом режиме можно задать период 1, длительность 1 и период 2, длительность 2 работы системного таймера. Программа представлена с исходным кодом на Borland C++ Builder 6.0. Важно!!! Для корректной работы timeBeginPeriod.exe и timer.exe должны находиться рядом, в одной директории. Проверка RTC-bug: 1. Проверку производим на свежезагруженной системе, без выполняющихся фоновых задач. Все фоновые процессы должны быть закрыты, поскольку они могут удерживать таймер на 1 мс, что помешает работе демонстрационной программы. 2. Запускаем Clockres - программу для контроля периода системного таймера. Измеренный период должен = 15.625 мс 3. Запускаем CPU-Z, переходим на закладку About, нажимаем кнопку Timers и кнопку Start, чтобы контроллировать частоты системных таймеров 4. Запускаем timer.exe. Устанавливаем режимы Период 1 = 1 мс, Длительность 1 = 0,2 секунды, Период 2 = 16 мс, Длительность 2 = 0,2 секунды и нажимаем кнопку Start. Эти режимы заданы режимами по-умолчанию. 5. В установленном режиме (по-умолчанию) будет происходить "накрутка" времени RTC таймера приблизительно +2 секунды за 1 минуту работы программы. При Длительности = 0.1 секунда, накрутка времени будет составлять +4 секунды за 1 минуту. Выводы: 1. Не смотря на то, что существует решение - программа Timer_Fix.exe, я предлагаю специалистам подробно изучить данную проблему с использованием нового инструмента - программы для накрутки времени Timer_v10 2. Может патчем файлов зафиксировать работу таймера на периоде 1 мс (0.977 мс), как это сделано в Windows 7 Состав архива: Clockres - программа для контроля периода системного таймера CPU-Z - в закладке About, кнопка Timers можно контроллировать частоты системных таймеров Neutron 1.07 - программа для контроля и синхронизации времени через интернет Timer_Fix (с исходным кодом) - фикс проблемы с уходом времени вперед (устанавливает таймер на 1мс) Timer_v10 (с исходным кодом) - программа накрутки времени, для демонстрации проблемы Скачать (2 МБ) - https://www.upload.ee/files/13095203/RTC_bug_demonstrations.zip.html
А если посмотреть, откуда процесс p_Info.hProcess получает параметры при запуске системы и занести туда нужные числа, как это делает программа при работе? Вот ещё по теме статья https://habr.com/ru/post/522212/
Ловля блох, какие-то микросекунды. У меня стоит ХР на Асус В250 и не замечаю никаких микросекунд, но спецы говорят, что если интенсивно работает Хром, то время может убежать на несколько секунд в день, какой кошмар. А эти несколько секунд вообще не парят, даже, если пусть несколько минут, у меня разве космодром Байконур, чтоб я секунды отсчитывал? Не думай о секундах свысока.... Если у тебя ушло время просто нажми правой педалью на часы и синхронизируй время с интернетом. Нашли проблему.... у кого по колено, тому жена не проблема. __________________________________________
С точностью времени будут проблемы в любом случае если не синхронизироваться постоянно по ntp. При отключении прерываний через cli - таймер перестает отсчитывать время. В зависимости от драйверов - задержка может изменяться от системы к системе. Тоесть вычислить сколько там ровно милисекунд в день надо подправить - не получится. В пределе можно нашлепать дров, который за день время на час уведет к примеру.
Так нашлёпали же, уже. Всё уже украдено, до нас. В архиве там лежит прога, которая висит в процессах, с единственной целью, корректировать время. Спецы пишут, это "решение костыльное, но другого пока придумать невозможно". Вот дались эти пару секунд в день, на что они влияют-то.
Да х/з. Надо сначала узнать что за задача. Могут и влиять. Может быть костыльное решение которое основывается на генераторе случайных чисел. Два компа должны одновременно сгенерить одно и то же, нпример. Какие-то казино или хрен его знает что еще. Мало-ли что там у них. Я вот думаю можно попробовать так уникально идентифицировать комп попробовать. Выбрать время когда он простаивает и чекнуть задержку. Тоже костыльно но... все эти методы уникальной идентификации костыльны по своему... Попробовать можно.
Костыль этот перехватывает состояние системного таймера, задаёт ему нужные параметры и периодически через установленные интервалы останавливает и перезапускает службу. Code: //--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include <mmsystem.h> #include "timer.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; int num = 1; int period1 = 1, period2 = 16; int duration = 0, duration1 = 0, duration2 = 10000; char txt[80]; STARTUPINFO sInfo; PROCESS_INFORMATION p_Info; char progparam[80]; DWORD dwProcessId; void start_process( int period, int duration) { sprintf( progparam, "timeBeginPeriod.exe %d %d 0", period, duration); setmem( &sInfo, sizeof(STARTUPINFO), 0); CreateProcess( NULL, // pointer to name of executable module progparam, // pointer to command line string NULL, // process security attributes NULL, // thread security attributes false, // handle inheritance flag CREATE_NO_WINDOW, // creation flags NULL, // pointer to new environment block NULL, // pointer to current directory name &sInfo, // pointer to STARTUPINFO &p_Info // pointer to PROCESS_INFORMATION ); } void stop_process() { if( p_Info.hProcess) { // TerminateProcess( hProcess, 0); WaitForSingleObject( p_Info.hProcess, INFINITE); // Wait until child process exits CloseHandle( p_Info.hProcess); // Close process and thread handles CloseHandle( p_Info.hThread); } } //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::FormShow(TObject *Sender) { Button1->Enabled = true; Button2->Enabled = false; Label2->Caption = "? ms"; } void __fastcall TForm1::FormDestroy(TObject *Sender) { timeBeginPeriod( 16); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { // Start if( !duration1 && !duration2) return; Button1->Enabled = false; Button2->Enabled = true; period1 = Edit1->Text.ToInt(); period2 = Edit2->Text.ToInt(); duration1 = Edit3->Text.ToDouble() * 1000; // ms duration2 = Edit4->Text.ToDouble() * 1000; // ms duration = 0; if( duration1) { num = 1; stop_process(); start_process( period1, duration1); // timeBeginPeriod( period1); sprintf( txt, "%d ms (%.1f s)", period1, duration/1000.0); } else { num = 2; stop_process(); start_process( period2, duration2); // timeBeginPeriod( period2); sprintf( txt, "%d ms (%.1f s)", period2, duration/1000.0); } Timer1->Interval = 100; // 100 ms Timer1->Enabled = true; Label2->Caption = txt; Application->ProcessMessages(); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { // Stop Button2->Enabled = false; Button1->Enabled = true; Timer1->Enabled = false; if( p_Info.hProcess) TerminateProcess( p_Info.hProcess, 0); stop_process(); timeBeginPeriod( 16); sprintf( txt, "%d ms", 16); Label2->Caption = txt; Application->ProcessMessages(); } //--------------------------------------------------------------------------- void __fastcall TForm1::Timer1Timer(TObject *Sender) { duration += Timer1->Interval; switch( num) { case 1: if( duration >= duration1) { duration = 0; num = 2; stop_process(); start_process( period2, duration2); // timeBeginPeriod( period2); } break; case 2: if( duration >= duration2) { duration = 0; if( duration1) { num = 1; stop_process(); start_process( period1, duration1); // timeBeginPeriod( period1); } } break; } sprintf( txt, "%d ms (%.1f s)", (num == 1) ? period1 : period2, duration/1000.0); Label2->Caption = txt; Application->ProcessMessages(); } //---------------------------------------------------------------------------
Ты же не будешь на два современных железа накатывать два ХР, чтобы сделать одно казино. Вечер по стеклу размазан, на десерт дают стриптиз
Извращенцев на земле немало Но да, обычно они синхронизируются перед своими извращениями. Как-то примерно так: w32tm.exe /resync UPD: надо же, борланды до сих пор живы После 7-го Дельфина я ушь и забыл про них. Как-то ставил какую-то кособокую вырвиглазную херню новой версии, охренел от нее, закрыл и забыл с тех пор
Есть такая штука как Kerberos в AD доменах, так вот там разница во времени может сильно повлиять на то, сможет ли кто-то залогинится в систему или нет. Так как там стандартом максимальная разница по времени в 5 минут, если разницы будет больше, то ADC просто не даёт добро. Также это весело если ADC не один, а их несколько и у них часики по разному тикают, тогда может быть что какая-то часть пользователей сможет зайти, а другая часть нет. https://docs.microsoft.com/en-us/wi...-tolerance-for-computer-clock-synchronization
На современном домашнем компьютере, на который юзер накатил себе ХР для бытовых целей, на что может повлиять разница в неколько секунд?
В Активках обычно прописывают же синхронизацию по ntp. Вообще это дикая вещь которая х/з как работает. Бедные админы сидят и пытаются что-то рулить групповыми политиками но по факту нихера толком не работает и настройка этих политик занимает не один день. А потом никто не хочет ничего трогать чтобы все не навернулось к чертовой матери. Даже вспоминать противно. Мелкомягкие решили сделать все "для пользователя" чтобы были кнопочки и чекбоксики - а получилось так что если нажать не тот чекбоксик - оно может все завалиться к чертовой матери а найти тот чекбоксик который все завалил - та еще задача
Выбери вариант который больше нравится: Порт NTP закрывают на "огненной стене" NTP сервак переезжает в другую подсеть или получает другой ip половина серверов синхронизирует время от (разных) внутренних NTP серверов, а другая половина от наружных серверов прова и начинается веселье...
Ну это... как рубить сук на котором сидишь И это все еще только начало. Мы еще не начали обсуждать что будет если в этой сети поднят Exchange - сервер
А никто нигде и не жаловался. Если время ушло, естесственное событие, то правой педалью на часах оно синхронизируется с интернетом. Надуманная проблема, высосаная из пальца, нужна тебе только с целью умняк корячить. Но, на этом сайте ты лапшу не развесишь, тупи дальше, кроме таймера не сможешь придумать ничего, ты полный бубен "Вирусы на ХР не запускаются, это самая безопасная ось" - то есть, тебя прямо бери и заноси в Палату 6. А почему не запускаются? "А потому что гавнокод под ХР уже не пишут" - тебя просто пора госпитализировать на дурку, "гавнокод это вирусы". _____________________________
@winxpmod Если проблема, по вашим словам, присуща только семейству на основе Chromium, может, стоит не клепать костыли, а обратить внимание на его исходник и найти багу в нём?
Для меня не существенно, что ты там должен. Просто нет никакой проблемы подвести часы, если такая необходимость возникла. Потому что, накуй не нужны никакие лишние процессы, которые висят в задачах, а, уж, тем более, твои придурошные исследования, в тот момент, когда на винрейде давно сказано, что проблема решения не имеет. А никакого решения и не надо, потому что, самой проблемы нет, она несуществует.
А баг это не гугловский строго говоря. Это баг Венды, причем баг архитектурный. Исправлять такой баг придется довольно долго а после этого ловить бсоды. Гугл тут не при делах Он может дрючить таймер столько, сколько захочет. Вплоть до возгорания системного блока. Это нигде не воспрещается и не оговаривается.