Понимание sem_timedwait () - PullRequest
       9

Понимание sem_timedwait ()

0 голосов
/ 14 сентября 2018

Я читаю руководство по sem_timedwait() и не могу понять пример. В настоящее время я понимаю, что:

  • Если время ожидания sem_timedwait() истекло, он возвращает -1 и устанавливает errno в ETIMEDOUT. Поэтому я могу проверить, истекло ли оно, а не сигнализировано.
  • sem_timedwait() вернет 0, если это будет сигнализировано sem_post()

Так что я понимаю оператор if, но не понимаю цикл while. Таким образом, он будет зацикливаться, пока sem_timedwait() возвращает ошибку (?) И пока он сигнализируется вызовом sem_post()? (Я явно не понимаю определение "EINTR The call was interrupted by a signal handler")

Пример из man:

while ((s = sem_timedwait(&sem, &ts)) == -1 && errno == EINTR)
    continue;       /* Restart if interrupted by handler */

/* Check what happened */

if (s == -1) {
    if (errno == ETIMEDOUT)
        printf("sem_timedwait() timed out\n");
    else
        perror("sem_timedwait");
} else
    printf("sem_timedwait() succeeded\n");

Я думал, что это будет работать примерно так:

s = sem_timedwait(&sem, &ts)
if (errno == ETIMEDOUT) {
    // timed out after specified ts
}
else if (s == -1) {
    // error occurred
}
else {
    // interrupted by `sem_post()`, do something relying on shared resource
}

Ответы [ 2 ]

0 голосов
/ 14 сентября 2018

Любой процесс может получать сигналов .Если этот процесс выполняет системный вызов, который блокирует процесс при получении сигнала, системный вызов не будет выполнен, и глобальному errno будет присвоено специальное значение EINTR.Таким образом, процесс снова пробуждается и может предпринимать действия при получении сигнала.

Это не серьезный сбой, это в основном просто информация о том, что сигнал был получен, и можно снова безопасно выполнить тот же вызов.

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

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

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

0 голосов
/ 14 сентября 2018

Цикл while:

while ((s = sem_timedwait(&sem, &ts)) == -1 && errno == EINTR)
    continue;       /* Restart if interrupted by handler */

будет зацикливаться до тех пор, пока не произойдет либо вызов sem_timedwait (т. Е. Произойдет sem_post()), либо не произойдет ошибка, отличная от EINTR.

Ошибка EINTR обрабатывается специально, поскольку вызов sem_timedwait может быть прерван в любой момент сигналом.Это не обрабатывается как ошибка, а как прерывание (которое равно ), и в этом случае вызов просто повторяется.

...