#c #posix
#c #posix
Вопрос:
Я пишу функцию-оболочку sleep_new()
clock_nanosleep()
, для которой мне было бы проще приостановить поток.
// POSIX.1-2017 is what compiler is confined to.
#define _XOPEN_SOURCE 700
#include <stdint.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
// POSIX headers.
// Other headers
#include "sleep_new.h"
void sleep_new(long value, const char unit[3]){
// Create a timespec structure and set it's members.
// Members are added together!!! So to set time "1.5 s" we set "t.tv_sec = 1" and "t.tv_sec = 500000000".
// Members ".tv_sec" and ".tv_nsec" represent unit and not value!
struct timespec sleep_time;
// Set flags i.e. TIMER_ABSTIME to 0 to use relative instead of absolute time.
int flags = 0;
// Choose the clock i.e. CLOCK_MONOTONIC is a "clock_id" for the clock started at system start.
int clock_id = CLOCK_MONOTONIC;
// Set timespec structure's members according to the chosen unit.
if (!strcmp(unit, "s")) {
sleep_time.tv_sec = value;
sleep_time.tv_nsec = 0;
}
else if (!strcmp(unit, "ns")){
sleep_time.tv_sec = 0;
sleep_time.tv_nsec = value;
}
else if (!strcmp(unit, "us")){
sleep_time.tv_sec = 0;
sleep_time.tv_nsec = value * 1000;
}
else if (!strcmp(unit, "ms")){
sleep_time.tv_sec = 0;
sleep_time.tv_nsec = value * 1000000;
}
else{
puts("Unit not supported - choose between: s, ms, us, nsn");
}
// Because last argument is NULL in case of error, remaining time is not stored in "t".
clock_nanosleep(clock_id, flags, amp;sleep_time, NULL);
}
int main(int argc, char *argv[])
{
// Counter.
uint8_t i;
for(i = 0; i < 256; i ){
// Stdout is newline buffered. This is why we either have to include `n` at the end or flush() it manually.
// So uncomment one example A or B.
// A
//printf("%dn", i);
// B
printf("%d, ", i);
fflush(stdout);
// Because last argument is NULL in case of error, remaining time is not stored in "t".
sleep_new(1000, "ms");
}
return 0;
}
Если я вызываю эту функцию с sleep_new(1, "s")
помощью or sleep_new(2, "s")
, она работает нормально, потому что она устанавливает sleep_time.tv_nsec = 0;
и sleep_time.tv_sec = value;
.
В любых других сценариях, т.Е. sleep_new(1000, "ms")
Что-то не так, и режим сна не применяется. Я отладил приложение, и значения применяются к timespec
членам просто отлично, но clock_nanosec()
просто игнорируют их.
Я использую type long
для value
, потому что я прочитал здесь в POSIX, где заголовок time.h
определяет timespec
членов структуры tv_nsec
, которые нуждаются long
, и членов tv_sec
, которые используют time_t
, что, в свою очередь, определяется в заголовке sys/types.h
следующим образом:
time_t
должен быть целочисленным типом.
Поэтому, поскольку long
он также может содержать int
значения, я ожидал, что это сработает, но это не так. У кого-нибудь есть какие-либо предложения?
Ответ №1:
Это tv_nsec
количество наносекунд в секунду — 1000 * 1000000
наносекунд слишком много. Это 1 секунда! tv_nsec
должно варьироваться от 0
до 999999999
. Правильное вычисление может выглядеть так:
sleep_time.tv_sec = value / 1000;
sleep_time.tv_nsec = (value % 1000) * 1000000;
Комментарии:
1. Вот дерьмо. Я не знал, что
tv_nsec
это имеет верхний предел999999999
… Я думал, что у long есть диапазон-9223372036854775808
до922337203685477580
?2. Тип не имеет (почти) ничего общего с интерпретацией. и
long
имеет размер не менее 2 ^ 31 … 2 ^ 31 .3. Можете ли вы объяснить, почему вы использовали целочисленное деление, а затем модулирование и умножение?
4. Я не верю, что смогу. Если у вас число больше
1000
, например12345
, миллисекунд. Как бы вы извлекли из этого числа количество секунд и наносекунд? Возьмите лист бумаги и попытайтесь выяснить.