Реализовано ли usleep () в C как занятое ожидание? - PullRequest
13 голосов
/ 16 ноября 2011

Я создаю многопоточное приложение с pthreads и мне нужен поток, чтобы периодически проверять некоторые вещи. В течение промежутка времени этот поток не должен использовать процессор Это возможно с usleep()? usleep() не занят ожиданием? Или есть лучшее решение?

Ответы [ 6 ]

12 голосов
/ 16 ноября 2011

Функция usleep удалена из SUSv4. Вам, вероятно, следует использовать nanosleep вместо этого или таймеры (setitimer и т. Д.).

Как отмечает R .. в комментариях, должен ли сон быть реализован как ожидание занятости:

  • Поток будет продолжать использовать процессор
  • Другие (с более низким приоритетом) потоки не смогут запустить

Таким образом:

  • Некоторые могут использовать сигналы (я думаю, что SUSv3 упомянул SIGALARM?)
  • Некоторые могут использовать причудливые таймеры
11 голосов
/ 16 ноября 2011

(usleep не является частью стандарта C, но является древним стандартом POSIX, но см. Ниже)

Нет, спецификация POSIX usleep четко гласит

Функция usleep () приведет к приостановке вызывающего потока от казни ...

, так что для этого явно требуется, чтобы он приостанавливал выполнение и передавал ресурсы другим процессам или потокам.

Как уже упоминалось другими, функция POSIX nanosleep теперь заменяет usleep, и вы должны использовать это. C (начиная с C11) имеет функцию thrd_sleep, которая моделируется после nanosleep.

6 голосов
/ 17 ноября 2011

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

Остерегайтесь, что это не проверено, но что-то вроде этого:

int myNanoSleep(time_t sec, long nanosec)
{
   /* Setup timespec */
   struct timespec req;
   req.tv_sec = sec;
   req.tv_nsec = nanosec;

   /* Loop until we've slept long enough */
   do 
   {
      /* Store remainder back on top of the original required time */
      if( 0 != nanosleep( &req, &req ) )
      {
          /* If any error other than a signal interrupt occurs, return an error */
          if(errno != EINTR)
             return -1; 
      }
      else
      {
          /* nanosleep succeeded, so exit the loop */
          break;
      }
   } while( req.tv_sec > 0 || req.tv_nsec > 0 )
   return 0; /* Return success */
}

И если вам когда-нибудь понадобится разбудить поток для чего-то другого, кроме периодического тайм-аута, взгляните на условные переменные и pthread_cond_timedwait().

3 голосов
/ 16 ноября 2011

В Linux это реализовано с помощью системного вызова nanosleep , который не является занятым ожиданием.

Используя strace, я вижу, что вызов usleep(1) транслируется в nanosleep({0, 1000}, NULL).

2 голосов
/ 16 ноября 2011

usleep() - это функция библиотеки времени выполнения C. Она построена на системных таймерах.
nanosleep() - это системный вызов.

Только в MS-DOS и, подобно ilk, реализуют функции ожидания в ожидании занятости.,Любая актуальная операционная система, которая предлагает многозадачность, может легко обеспечить функцию сна в качестве простого расширения механизмов для координации задач и процессов.

0 голосов
/ 09 апреля 2013

Стоит отметить, что WINE [lazily?] Реализует usleep в качестве вызова select ():

#ifndef HAVE_USLEEP
int usleep (unsigned int useconds)
{
#if defined(__EMX__)
    DosSleep(useconds);
    return 0;
#elif defined(__BEOS__)
    return snooze(useconds);
#elif defined(HAVE_SELECT)
    struct timeval delay;

    delay.tv_sec = useconds / 1000000;
    delay.tv_usec = useconds % 1000000;

    select( 0, 0, 0, 0, &delay );
    return 0;
#else /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
    errno = ENOSYS;
    return -1;
#endif /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
}
#endif /* HAVE_USLEEP */

Стоит также упомянуть, что nanosleep (в GLIBC) выглядит чуть больше, чем пустая функциявызов (что-нибудь еще, и задержка может сместиться в микросекундный диапазон).

/* Pause execution for a number of nanoseconds.  */
int
__libc_nanosleep (const struct timespec *requested_time,
                  struct timespec *remaining)
{
  __set_errno (ENOSYS);
  return -1;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...