Как заставить поток спать / блокировать на наносекунды (или хотя бы миллисекунды) - PullRequest
11 голосов
/ 27 апреля 2011

Как я могу заблокировать мой поток (возможно, процесс) на наносекунды или, может быть, на миллисекунды (по крайней мере) период?

Обратите внимание, что я не могу использовать сон, потому что аргумент для сна всегда в секундах.

Ответы [ 7 ]

10 голосов
/ 27 апреля 2011

nanosleep или clock_nanosleep - это функция, которую вы должны использовать (последняя позволяет вам указывать абсолютное время, а не относительное время, и использовать монотонные часы или другие часы, а не только часы реального времени, которые могут работать в обратном направлении.если оператор сбрасывает его).

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

Также, если возможно, я бы предложил использовать вызов, который блокирует ожидание события, а не спитдля крошечных интервалов, а затем опрос.Например, pthread_cond_wait, pthread_cond_timedwait, sem_wait, sem_timedwait, select, read и т. Д. В зависимости от того, какую задачу выполняет ваш поток и как он синхронизируется с другими потоками и / или взаимодействует свнешний мир.

5 голосов
/ 27 апреля 2011

Один относительно переносимый способ - использовать select() или pselect() без файловых дескрипторов:

void sleep(unsigned long nsec) {
    struct timespec delay = { nsec / 1000000000, nsec % 1000000000 };
    pselect(0, NULL, NULL, NULL, &delay, NULL);
}
3 голосов
/ 27 апреля 2011

nanosleep позволяет указать точность сна до наносекунд.Однако фактическое разрешение вашего сна, вероятно, будет намного больше из-за ограничений ядра / процессора.

3 голосов
/ 27 апреля 2011

Использование любого варианта сна для pthreads, поведение не гарантируется. Все потоки также могут спать, поскольку ядро ​​не знает о различных потоках. Следовательно, требуется решение, которое может обрабатывать библиотека pthread, а не ядро.

Более безопасное и чистое решение - pthread_cond_timedwait ...

pthread_mutex_t fakeMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t fakeCond = PTHREAD_COND_INITIALIZER;

void mywait(int timeInSec)
{
struct timespec timeToWait;
struct timeval now;
int rt;

gettimeofday(&now,NULL);

timeToWait.tv_sec = now.tv_sec + timeInSec;
timeToWait.tv_nsec = now.tv_usec*1000;

pthread_mutex_lock(&fakeMutex);
rt = pthread_cond_timedwait(&fakeCond, &fakeMutex, &timeToWait);
pthread_mutex_unlock(&fakeMutex);
printf("\nDone\n");
}

void* fun(void* arg)
{
printf("\nIn thread\n");
mywait(5);
}

int main()
{
pthread_t thread;
void *ret;

pthread_create(&thread, NULL, fun, NULL);
pthread_join(thread,&ret);
}

Для pthread_cond_timedwait вам нужно указать, сколько времени ждать от текущего времени.

Теперь при использовании функции mywait () будет спать только поток, вызывающий ее, а не другие потоки.

3 голосов
/ 27 апреля 2011

Попробуйте usleep () . Да, это не даст вам наносекундную точность, но микросекунды тоже будут работать => миллисекунды.

2 голосов
/ 27 апреля 2011

Точное разрешение с точностью до наносекунды в обычной ОС Linux будет невозможным из-за того, что обычно дистрибутивы Linux не являются (жесткими) операционными системами реального времени. Если вам действительно нужен этот мелкозернистый контроль над временем, рассмотрите возможность использования такой операционной системы.

В Википедии есть список некоторых операционных систем реального времени: http://en.wikipedia.org/wiki/RTOS (обратите внимание, что в нем не указано, мягкие они или жесткие в реальном времени, поэтому вам придется провести некоторое исследование).

1 голос
/ 21 июня 2011

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

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

...