我使用startx来启动X,这将计算我的.xinitrc。在我的.xinitrc中,我使用/usr/bin/mywm.启动我的窗口管理器现在,如果我杀死我的WM(为了f.e.测试其他一些WM), X也将终止,因为.xinitrc脚本到达了EOF。 所以我在.xinitrc的末尾添加了这个:
while true; do sleep 10000; done
这样,如果我终止WM, X就不会终止。现在我的问题是:我如何做一个无限睡眠而不是循环睡眠?是否有类似于冻结脚本的命令?
我使用startx来启动X,这将计算我的.xinitrc。在我的.xinitrc中,我使用/usr/bin/mywm.启动我的窗口管理器现在,如果我杀死我的WM(为了f.e.测试其他一些WM), X也将终止,因为.xinitrc脚本到达了EOF。 所以我在.xinitrc的末尾添加了这个:
while true; do sleep 10000; done
这样,如果我终止WM, X就不会终止。现在我的问题是:我如何做一个无限睡眠而不是循环睡眠?是否有类似于冻结脚本的命令?
当前回答
那么发送一个SIGSTOP给它自己呢?
这将暂停进程,直到接收到SIGCONT。在你的情况下,永远不会。
kill -STOP "$$";
# grace time for signal delivery
sleep 60;
其他回答
那么发送一个SIGSTOP给它自己呢?
这将暂停进程,直到接收到SIGCONT。在你的情况下,永远不会。
kill -STOP "$$";
# grace time for signal delivery
sleep 60;
这种方法不会消耗任何资源来保持进程的活动。
while :; do :; done & kill -STOP $! && wait
分解
而:;做的事:;done &在后台创建一个虚拟进程 杀-停止$!停止后台进程 等待后台进程,这将永远阻塞,因为后台进程之前已经停止
笔记
只能从脚本文件中工作。
while :; do read; done
没有等待孩子睡觉的过程。
让我来解释一下为什么无限睡眠是有效的,尽管它没有被记录下来。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]转换为浮点值,并使用转换函数cl_strtod()将其存储为*s。
cl_strtod()
从coreutils/lib/cl- strtod.c.可以看到,cl_strtod()使用strtod()将字符串转换为浮点值。
strtod()
根据man3 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的float和long双类似物。 在支持无穷大的实现中,HUGE_VAL、HUGE_VALF和HUGE_VALL可以是正无穷大。
在§7.12.1-5中
如果浮动结果溢出且默认舍入生效,则该函数根据返回类型返回宏HUGE_VAL、HUGE_VALF或HUGE_VALL的值
理解xnanosleep
现在我们理解了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/ dtotimspec .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/ timspech就足够了。
_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;
}
“无限睡眠”确实做到了它所建议的,而且没有虐待猫。