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
and INFINITY
(両方とも大文字と小文字を区別しない)はと見なされHUGE_VAL
ます。
HUGE_VAL
家族
C標準としてN1570を使用します。HUGE_VAL
、HUGE_VALF
およびHUGE_VALL
マクロは§7.12-3で定義されています
マクロ
HUGE_VAL
は正の二重定数式に展開されますが、必ずしも浮動小数点数として表現できるわけではありません。マクロ
HUGE_VALF
HUGE_VALL
は、それぞれfloatとlong doubleの類似物です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()
この関数は、型の引数を型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;
}