更新:这越来越不是一个问题,而是一个总结。哦,好吧...
不过,还有很多不清楚的地方。我发现其中有些相当出乎意料。特别是,您获得的行为取决于shell和底层操作系统。我创建了一个表,总结了可变性的程度。我还包括了一个脚本的代码,我用来自动获得这些结果。最后一个测试需要root权限,如果注释掉test_shell_sudo$shell
,则可以阻止它运行。
| | Darwin/zsh | Darwin/bash | FreeBSD/zsh | FreeBSD/bash | FreeBSD/dash | Linux/zsh | Linux/bash | Linux/dash | | ulimit -t sets | soft limit | both limits | soft limit | both limits | both limits | soft limit | both limits | both limits | | ulimit -t gets | soft limit | soft limit | soft limit | soft limit | soft limit | soft limit | soft limit | soft limit | | Hard limits can be set below the soft limit | yes | no | yes | yes | yes | yes | no | no | | Soft limits can be set above the hard limit | yes | no | yes | no | no | yes | no | no | | Hard limits can be raised without privileges | yes | no | yes | no | no | yes | no | no | | soft signal | SIGXCPU | SIGXCPU | SIGXCPU | SIGXCPU | SIGXCPU | SIGXCPU | SIGXCPU | SIGXCPU | | hard signal | SIGXCPU | SIGXCPU | SIGKILL | SIGKILL | SIGKILL | SIGKILL | SIGKILL | SIGKILL | | Number of SIGXCPUs sent | one | one | one | one | one | multiple | multiple | multiple | | Raising soft beyond hard limit raises it | yes | impossible* | yes | no | no | yes | impossible* | impossible* | * even as root
#!/usr/bin/env bash
get_sigcode() {
/bin/kill -l |
tr '\n[a-z]' ' [A-Z]' |
awk -v name=$1 '
{ for (i=1; i<=NF; ++i) if ($i == name) print i }'
}
create_runner() {
cat > sig.c <<'EOF'
#include <stdlib.h>
#include <stdio.h>
int
main()
{
int runs = 0;
double x = 0.0;
for (;;runs++) {
x += (double)rand() / RAND_MAX;
if (x >= 1e7) {
printf("Took %d iterations to reach 1000.\n", runs);
x = 0.0;
runs = 0;
}
}
return 0;
}
EOF
cc sig.c -o sig
rm -f sig.c
echo Successfully compiled sig.c
}
create_counter() {
cat > sigcnt.c <<'EOF'
#include <stdatomic.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
sig_atomic_t sig_received;
void handle_signal(int signum) {
sig_received = signum;
}
int
main()
{
signal(SIGXCPU, handle_signal);
int sigxcpu_cnt = 0;
time_t start, now;
time(&start);
int runs = 0;
double x = 1;
for (;;) {
if (sig_received == SIGXCPU) {
sigxcpu_cnt++;
sig_received = 0;
}
time(&now);
if (now - start > 5) {
switch (sigxcpu_cnt) {
case 0:
fprintf(stderr, "none\n");
exit(0);
case 1:
fprintf(stderr, "one\n");
exit(0);
default:
fprintf(stderr, "multiple\n");
exit(0);
}
}
// Do something random that eats CPU (sleeping is not an option)
x += (double)rand() / RAND_MAX;
if (x >= 1e7) {
printf("Took %d iterations to reach 1000.\n", runs);
x = 0.0;
runs = 0;
}
}
}
EOF
cc sigcnt.c -o sigcnt
rm -f sigcnt.c
echo Successfully compiled sigcnt.c
}
echo_underscored() {
out1=$1
out2=''
for ((i=0; i < ${#out1}; ++i)); do
out2+='='
done
echo $out1
echo $out2
}
test_shell() {
shell=$1
echo_underscored "Testing shell: $shell"
f() {
$shell -c 'ulimit -St 3; ulimit -t 2; ulimit -Ht; ulimit -St' | tr -d '\n'
}
case `f` in
22)
t_sets='both limits';;
unlimited2)
t_sets='soft limit';;
*)
echo UNEXPECTED;;
esac
echo "ulimit -t sets: ${t_sets}"
f() {
$shell -c 'ulimit -St 3; ulimit -Ht 4; ulimit -St 3; ulimit -t'
}
case `f` in
3)
t_gets='soft limit';;
*)
echo UNEXPECTED;;
esac
echo "ulimit -t gets: ${t_gets}"
f() {
$shell -c 'ulimit -St 2; ulimit -Ht 1' >/dev/null 2>&1 &&
echo yes || echo no
}
ht_can_set_below_soft=`f`
echo "Hard limits can be set below the soft limit: ${ht_can_set_below_soft}"
f() {
$shell -c 'ulimit -St 1; ulimit -Ht 2; ulimit -St 3' >/dev/null 2>&1 &&
echo yes || echo no
}
st_can_set_above_hard=`f`
echo "Soft limits can be set above the hard limit: ${st_can_set_above_hard}"
f() {
$shell -c 'ulimit -St 1; ulimit -Ht 2; ulimit -Ht 3' >/dev/null 2>&1 &&
echo yes || echo no
}
hard_can_be_raised=`f`
echo "Hard limits can be raised without privileges: ${hard_can_be_raised}"
f() {
$shell -c 'ulimit -St 1; ./sig' >/dev/null 2>&1
echo $?
}
case $((`f` - 128)) in
${sigxcpu})
soft_signal=SIGXCPU;;
${sigkill})
soft_signal=SIGKILL;;
*)
echo UNEXPECTED;
esac
echo "soft signal: ${soft_signal}"
f() {
$shell -c 'ulimit -St 1; ulimit -Ht 1; ./sig' >/dev/null 2>&1
echo $?
}
case $((`f` - 128)) in
${sigxcpu})
hard_signal=SIGXCPU;;
${sigkill})
hard_signal=SIGKILL;;
*)
echo UNEXPECTED;;
esac
echo "hard signal: ${hard_signal}"
f() {
$shell -c 'ulimit -St 1; ./sigcnt 2>&1 >/dev/null'
}
sigxcpus_sent=`f`
echo "Number of SIGXCPUs sent: ${sigxcpus_sent}"
}
test_shell_sudo() {
shell=$1
echo_underscored "Testing shell with sudo: $shell"
f() {
sudo $shell -c 'ulimit -St 1; ulimit -Ht 1; ulimit -St 2 && ulimit -Ht' \
2>/dev/null;
}
out=`f`; ret=$?;
if [[ $ret == 0 ]]; then
case $out in
1)
raising_soft_beyond_hard='no';;
2)
raising_soft_beyond_hard='yes';;
*)
echo UNEXPECTED;;
esac
else
raising_soft_beyond_hard='impossible'
fi
echo "Raising soft beyond hard limit raises it: ${raising_soft_beyond_hard}"
}
main() {
echo "Testing on platform: $(uname)"
sigxcpu=$(get_sigcode XCPU)
sigkill=$(get_sigcode KILL)
echo Number of signal SIGXCPU: ${sigxcpu}
echo Number of signal SIGKILL: ${sigkill}
create_runner
create_counter
echo
for shell in zsh bash dash; do
which $shell >/dev/null || continue;
test_shell $shell
echo
done
for shell in zsh bash dash; do
which $shell >/dev/null || continue;
test_shell_sudo $shell
echo
done
}
main
相应的要点还附带了一个更好的表格。
首先,这里有ulimits的绝对规则,包括shell在内的所有进程都必须遵守:
考虑到这一点:
软极限,是的。硬性限制,没有。
bash似乎认为不,而zsh认为是。
$ strace -e setrlimit zsh -c 'ulimit -t 1'
setrlimit(RLIMIT_CPU, {rlim_cur=1, rlim_max=RLIM64_INFINITY}) = 0
$ strace -e setrlimit bash -c 'ulimit -t 1'
setrlimit(RLIMIT_CPU, {rlim_cur=1, rlim_max=1}) = 0
zsh% ulimit -H -t 1
zsh% ( while true; do true; done ) # is a child, soon killed
zsh% while true; do true; done # not a child, never dies
如果同时设置这两个限制,它们将应用于当前shell,如bash
中所示:
zsh% ulimit -SH -t 1
zsh% while true; do true; done # will now die, just like bash
我不知道这背后的理由是什么。
问题内容: package main 该代码可以很好地工作。但是,如果按如下所示更改方法,则会导致死循环。区别在于将替换为。为什么? 问题答案: 因为程序包检查要打印的值是否具有方法(或换句话说:是否实现接口),如果是,则将调用它以获取值的表示形式。 软件包doc中对此进行了说明: […]如果操作数实现String()字符串方法,则将调用该方法将对象转换为字符串,然后根据动词的要求对其进行格式化(
问题内容: 从理论上讲,如果我将所有cookie从selenium的对象复制到对象,那么请求是否能够继续进行,就好像会话没有中断一样? 具体来说,我对编写自动化感兴趣,我可以通过Selenium到达网页上的特定位置,然后将特定的下载链接传递到,该链接将下载并验证文件中特定字节的内容,有时甚至是完整文件。(下载的文件的值将根据我在selenium中的相互作用而变化) 问题答案: 是的,肯定可以。以下
我一直在学习如何使用java编程,但我还没有明确解释的和方法的区别。第二个只是将LinkedList对象中的所有元素作为数组返回,对吗?但是,第一个呢? 编辑: 我的意思是,我从甲骨文中阅读了文档,它说: 返回一个数组,其中包含此列表中所有元素的正确顺序(从第一个元素到最后一个元素);返回数组的运行时类型是指定数组的运行时类型。如果列表适合指定的数组,则返回该数组。否则,将使用指定数组的运行时类型
本文向大家介绍完全虚拟化和准虚拟化之间的区别,包括了完全虚拟化和准虚拟化之间的区别的使用技巧和注意事项,需要的朋友参考一下 在本文中,我们将了解完全虚拟化和半虚拟化之间的区别 全面虚拟化 此过程由IBM于1966年引入。它被认为是第一个用于服务器虚拟化的软件解决方案。它使用二进制翻译和直接方法。 在这种情况下,使用虚拟机将来宾操作系统与虚拟化层和硬件完全隔离。 完全虚拟化的示例包括Microsof
问题内容: 我一直认为,子shell程序不是子进程,而是同一进程中的另一个shell程序环境。 我使用一组基本的内置函数: 在另一个终端上: 因此,kornShell(ksh)中没有子进程。 输入bash,使用相同的命令,其行为似乎有所不同: 因此,bash中的一个子进程。 通过阅读bash手册页,很明显,为子shell创建了另一个进程,但是它伪造了$$,这很时髦。 是bash和ksh之间的区别是
我正在测试上面的代码。两者给我的结果是一样的。我正试图理解第1、2和6行之间的区别。我可以通过这两种方法获得相同的结果。