Я почти уверен, что вопрос банален, но почему-то у меня не получается найти хорошее решение.
Есть программа сидящая в бесконечном цикле. Раз в минуту этот цикл надо прервать и выполнить некие действия. Причём прервать нужно именно в начале минуты, т.е. после наступления нулевой секунды. Время может корректироваться по GPS, поэтому привязываться нужно к началу минуты, а не к временному интервалу.
Как это можно сделать грамотно? Попадающиеся мне решения основаны на опросе часов с функцией sleep/usleep. Но это значительно нагружает процессор, а программа в идеале должна сидеть и не занимать процессорное время, пока не придёт начало минуты.
Нет, я хочу сказать, что мне нужно чётко привязываться к началу минуты. Ибо я не знаю сколько по времени займёт выполнение программой своих основных функций. Если ставить sleep ровно на минуту, то соответственно временной интервал будет минута + время на работу функций. Соответственно временной интервал будет со временем "уплывать" от начала минуты. Кроме того системное время может быть скорректировано и определённый промежуток между нулевыми секундами может стать меньше/больше минуты. А если ставить sleep меньше то будут пустые циклы, которые будут грузить процессор. Чем меньше sleep - тем точнее привязка, но больше нагрузка. А хотелось бы этого избежать.
можно ставить sleep на секунду и каждую секунду проверять - не началась ли минута.
когда процесс находиться в sleep он не использует процессор вообще ни как, так что ничего он не нагружает.
И точность будет +/- 1 секунда. Грубовато. А если проверять хотя бы 20 раз в секунду, то программа уже хочет 30% процессора. неужели нет решения без sleep'ов?
while (1) {
fResult = adc_main_collect(); //основная функция сбора данных
if (fResult != 0){
printf("\n ADC cycle failure. Error %d\n", fResult);
return fResult ;
usleep(50000);
}
}
Текущее время проверялось уже внутри основной функции и если оно было с нулевой секундой, то всё шло дальше. Если нет, то просто шёл возврат из функции. И увеличение частоты вызова функции (даже если она ничего не делала кроме проверки времени) наглухо забивало процессор.
Если есть доступ к регистрам самого процессора, то STM32, например, имеет два регистра для генерации событий по часам точного времени. Там можно задать событие по нулю секунд независимо от остального времени.
Вот это уже больше похоже на правду. Там стоит bcm2835 (обычная Raspberry Pi). Нагуглил для него некую библиотеку на С, надо её покурить. У процессора наверняка должны быть прерывания по таймеру.
Нет, к сожалению не под Windows. У меня Linux на ARM. Под Windows и x86 в принципе не было бы проблем использовать sleep - там запаса процессора больше.
Бесконечный цикл со sleep не очень элегантное решение. Если Вам ничего не мешает перейти на C++, то соберите boost и воспользуйтесь asio. Вот пример www.boost.org/doc/libs/1_49_0/doc/html/boost_asio/... адаптируйте его под свои нужды. Еще посмотрите на boost::posix_time::time_period.