我使用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就不会终止。现在我的问题是:我如何做一个无限睡眠而不是循环睡眠?是否有类似于冻结脚本的命令?
当前回答
我最近需要这样做。我提出了下面的函数,它将允许bash永远休眠而不调用任何外部程序:
snore()
{
local IFS
[[ -n "${_snore_fd:-}" ]] || { exec {_snore_fd}<> <(:); } 2>/dev/null ||
{
# workaround for MacOS and similar systems
local fifo
fifo=$(mktemp -u)
mkfifo -m 700 "$fifo"
exec {_snore_fd}<>"$fifo"
rm "$fifo"
}
read ${1:+-t "$1"} -u $_snore_fd || :
}
注意:我之前发布了一个版本,每次都会打开和关闭文件描述符,但我发现在一些系统上,每秒执行数百次这样的操作最终会锁定。因此,新的解决方案在函数调用之间保持文件描述符。反正巴斯一出去就会收拾干净的。
它可以像/bin/sleep一样被调用,它将在请求的时间内休眠。调用时不带参数,它将永远挂起。
snore 0.1 # sleeps for 0.1 seconds
snore 10 # sleeps for 10 seconds
snore # sleeps forever
在我的博客上有一篇写得太多细节的文章
其他回答
让我来解释一下为什么无限睡眠是有效的,尽管它没有被记录下来。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;
}
与其杀死窗口管理器,不如尝试使用——replace或-replace(如果可用的话)运行新的窗口管理器。
“无限睡眠”确实做到了它所建议的,而且没有虐待猫。
while :; do read; done
没有等待孩子睡觉的过程。
我最近需要这样做。我提出了下面的函数,它将允许bash永远休眠而不调用任何外部程序:
snore()
{
local IFS
[[ -n "${_snore_fd:-}" ]] || { exec {_snore_fd}<> <(:); } 2>/dev/null ||
{
# workaround for MacOS and similar systems
local fifo
fifo=$(mktemp -u)
mkfifo -m 700 "$fifo"
exec {_snore_fd}<>"$fifo"
rm "$fifo"
}
read ${1:+-t "$1"} -u $_snore_fd || :
}
注意:我之前发布了一个版本,每次都会打开和关闭文件描述符,但我发现在一些系统上,每秒执行数百次这样的操作最终会锁定。因此,新的解决方案在函数调用之间保持文件描述符。反正巴斯一出去就会收拾干净的。
它可以像/bin/sleep一样被调用,它将在请求的时间内休眠。调用时不带参数,它将永远挂起。
snore 0.1 # sleeps for 0.1 seconds
snore 10 # sleeps for 10 seconds
snore # sleeps forever
在我的博客上有一篇写得太多细节的文章