왜 sleep infinity문서화되지 않았지만 작동 하는지 설명하겠습니다 . jp48의 답변 도 유용합니다.
가장 중요한 것 : inf또는 infinity(대소 문자를 구분하지 않음) 을 지정 하면 구현에서 허용하는 가장 긴 시간 동안 (예 : HUGE_VAL및 값이 더 작은) 휴면 상태가 될 수 있습니다 TYPE_MAXIMUM(time_t).
이제 세부 사항을 파헤쳐 보자. sleep명령 소스 코드는 coreutils / src / sleep.c 에서 읽을 수 있습니다 . 기본적으로 함수는 다음을 수행합니다.
double s; //seconds
xstrtod (argv[i], &p, &s, cl_strtod); //`p` is not essential (just used for error check).
xnanosleep (s);
이해 xstrtod (argv[i], &p, &s, cl_strtod)
xstrtod()
gnulib / lib / xstrtod.c 에 따르면 , 호출은 변환 함수를 사용하여 xstrtod()문자열 argv[i]을 부동 소수점 값 *s으로 변환하여 저장합니다 cl_strtod().
cl_strtod()
에서 볼 수 있듯이 로 coreutils / lib 디렉토리 / CL-strtod.c , cl_strtod()사용, 부동 소수점 값에 문자열로 변환합니다 strtod().
strtod()
에 따르면 man 3 strtod, strtod()유형의 값에 문자열로 변환합니다 double. 맨 페이지 말한다
(문자열의 초기 부분)의 예상 형식은 ... 또는 (iii) 무한대 또는 ...
무한대는
무한대는 대소 문자를 무시하고 "INF"또는 "INFINITY"입니다.
문서가 알려 주지만
올바른 값으로 오버플로가 발생하면 더하기 또는 빼기 HUGE_VAL( HUGE_VALF, HUGE_VALL)가 반환됩니다.
무한대가 어떻게 취급되는지는 명확하지 않다. 소스 코드 gnulib / lib / strtod.c를 보자 . 우리가 읽고 싶은 것은
else if (c_tolower (*s) == 'i'
&& c_tolower (s[1]) == 'n'
&& c_tolower (s[2]) == 'f')
{
s += 3;
if (c_tolower (*s) == 'i'
&& c_tolower (s[1]) == 'n'
&& c_tolower (s[2]) == 'i'
&& c_tolower (s[3]) == 't'
&& c_tolower (s[4]) == 'y')
s += 5;
num = HUGE_VAL;
errno = saved_errno;
}
따라서, INF및 INFINITY(대소 문자 구별)는 다음과 같이 간주된다 HUGE_VAL.
HUGE_VAL 가족
N1570 을 C 표준으로 사용합시다 . HUGE_VAL, HUGE_VALF및 HUGE_VALL매크로에 정의되어 §7.12-3
매크로
HUGE_VAL
는 양의 상수 상수로 확장되며 반드시 부동 소수점으로 표현할 필요는 없습니다. 매크로
HUGE_VALF
HUGE_VALL
는 각각 부동 및 긴 이중 아날로그입니다 HUGE_VAL.
HUGE_VAL, HUGE_VALF및 HUGE_VALL인피니티를 지원하는 구현에서 긍정적 인 인피니티 일 수 있습니다.
§7.12.1-5
부동 결과가 오버 플로우 및 기본 반올림이 적용되는 경우,이 함수는 매크로의 값을 반환 HUGE_VAL, HUGE_VALF또는 HUGE_VALL반환 형식에 따라
이해 xnanosleep (s)
이제 우리는의 모든 본질을 이해합니다 xstrtod(). 위의 설명에서, xnanosleep(s)우리가 실제로 본 것은 실제로 의미 하는 것은 명백합니다 xnanosleep(HUGE_VALL).
xnanosleep()
소스 코드 gnulib / lib / xnanosleep.c에 따르면 xnanosleep(s)본질적으로 다음을 수행합니다.
struct timespec ts_sleep = dtotimespec (s);
nanosleep (&ts_sleep, NULL);
dtotimespec()
이 함수는 type 인수를 type double객체 로 변환합니다 struct timespec. 매우 간단하므로 소스 코드 gnulib / lib / dtotimespec.c를 인용 하겠습니다 . 모든 의견은 저에 의해 추가됩니다.
struct timespec
dtotimespec (double sec)
{
if (! (TYPE_MINIMUM (time_t) < sec)) //underflow case
return make_timespec (TYPE_MINIMUM (time_t), 0);
else if (! (sec < 1.0 + TYPE_MAXIMUM (time_t))) //overflow case
return make_timespec (TYPE_MAXIMUM (time_t), TIMESPEC_HZ - 1);
else //normal case (looks complex but does nothing technical)
{
time_t s = sec;
double frac = TIMESPEC_HZ * (sec - s);
long ns = frac;
ns += ns < frac;
s += ns / TIMESPEC_HZ;
ns %= TIMESPEC_HZ;
if (ns < 0)
{
s--;
ns += TIMESPEC_HZ;
}
return make_timespec (s, ns);
}
}
이후 time_t일체형으로 정의된다 (§7.27.1-3 참조), 우리가 유형의 최대 값이 가정 자연 time_t보다 작다 HUGE_VAL(유형 double우리가 오버 플로우하는 경우 입력 수단). (실제로이 절차는 본질적으로 동일하기 때문에이 가정은 필요하지 않습니다.)
make_timespec()
우리가 올라 가야하는 마지막 벽은 make_timespec()입니다. 운 좋게도 소스 코드 gnulib / lib / timespec.h 를 인용하면 충분합니다.
_GL_TIMESPEC_INLINE struct timespec
make_timespec (time_t s, long int ns)
{
struct timespec r;
r.tv_sec = s;
r.tv_nsec = ns;
return r;
}