왜 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;
}