[linux] 배쉬 : 무한 수면 (무한 차단)
startx
내 X를 평가하는 데 사용 합니다 .xinitrc
. 내 .xinitrc
에서을 사용하여 창 관리자를 시작 /usr/bin/mywm
합니다. 이제 WM을 죽이면 (다른 WM을 테스트하기 위해) .xinitrc
스크립트가 EOF에 도달 했기 때문에 X도 종료됩니다 . 그래서 나는 이것을 내 끝에 추가했다 .xinitrc
:
while true; do sleep 10000; done
이렇게하면 WM을 죽이면 X가 종료되지 않습니다. 이제 내 질문 : 루핑 수면 대신 무한 수면을 어떻게 할 수 있습니까? 스크립트를 정지시키는 것과 같은 명령이 있습니까?
친애하는
답변
sleep infinity
고양이 학대없이 제안하고 작동하는 것을 정확하게 수행합니다.
답변
tail
차단하지 않습니다
항상 그렇듯이 : 모든 것에 대해 짧고 이해하기 쉽고 따르기 쉽고 완전히 잘못된 대답이 있습니다. 여기이 tail -f /dev/null
범주에 속합니다.)
당신이 그것을 보시면 strace tail -f /dev/null
이 솔루션은 차단되지 않습니다! sleep
Linux와 같은 inotify
시스템 과 같은 귀중한 리소스를 사용하기 때문에 문제 의 솔루션 보다 훨씬 나쁩니다 . 또한 루프 를 /dev/null
만들기 위해 쓰는 다른 프로세스 tail
. (Ubuntu64 16.10에서는 이미 사용량이 많은 시스템에서 초당 10 회의 syscall이 추가됩니다.)
문제는 차단 명령이었습니다
불행히도, 그런 것은 없습니다 ..
읽는다 : 나는 이것을 쉘로 직접 보관할 방법을 모른다.
모든 sleep infinity
신호는 심지어 일부 신호에 의해 중단 될 수 있습니다. 따라서 예외적으로 반환되지 않는지 확인하려면 이미 수행 한 것처럼 루프에서 실행해야합니다 sleep
. (Linux의 경우) /bin/sleep
24 일에 한도를 정했다는 점을 명심하십시오 ( strace sleep infinity
따라서 살펴보십시오 ).
while :; do sleep 2073600; done
(내가 sleep
24 일보다 높은 값을 위해 내부적으로 루프를 믿지만 이것은 차단하지 않고 매우 느리게 반복됩니다.이 루프를 외부로 옮기지 않는 이유는 무엇입니까?)
.. 그러나 당신은 이름 없는와 꽤 가까이 올 수 있습니다 fifo
프로세스에 신호가 전송되지 않는 한 실제로 차단되는 것을 만들 수 있습니다. 다음 bash 4
과 같이 2 개의 PID와 1을 사용합니다 fifo
.
bash -c 'coproc { exec >&-; read; }; eval exec "${COPROC[0]}<&-"; wait'
원하는 strace
경우 이것이 실제로 차단 되는지 확인할 수 있습니다.
strace -ff bash -c '..see above..'
이것이 어떻게 구성 되었는가
read
입력 데이터가없는 경우 차단합니다 (다른 답변 참조). 그러나 tty
(일명. stdin
)은 일반적으로 사용자가 로그 아웃 할 때 닫히기 때문에 좋은 소스가 아닙니다. 또한에서 일부 입력을 훔칠 수 있습니다 tty
. 좋지 않아.
read
차단 하려면 fifo
아무것도 반환하지 않는 것과 같은 것을 기다릴 필요가 있습니다. 에서 bash 4
정확히 같은 우리를 제공 할 수있는 명령이 있습니다 fifo
: coproc
. 차단 read
( 대기자)을 기다리면 coproc
완료됩니다. 슬프게도 이것은 두 개의 PID와 a를 열어 두어야합니다 fifo
.
명명 된 변형 fifo
named를 사용하지 않으면 fifo
다음과 같이 할 수 있습니다.
mkfifo "$HOME/.pause.fifo" 2>/dev/null; read <"$HOME/.pause.fifo"
읽기에 루프를 사용하지 않는 것은 약간 느슨하지만, fifo
원하는만큼 자주 재사용 하고 read
s를 사용하여 터미널을 사용할 수 있습니다 touch "$HOME/.pause.fifo"
(하나 이상의 읽기 대기가있는 경우 모든 것이 한 번에 종료 됨).
또는 Linux pause()
syscall을 사용하십시오.
무한 차단을 위해 리눅스 커널 호출이 있는데, pause()
우리가 원하는 것을한다 : 신호가 도착할 때까지 영원히 기다린다. 그러나 이것에 대한 사용자 공간 프로그램은 아직 없습니다.
씨
그러한 프로그램을 만드는 것은 쉽습니다. 여기라는 매우 작은 리눅스 프로그램을 만들 수있는 조각이다 pause
무기한 (요구 일시 정지 diet
, gcc
등)
printf '#include <unistd.h>\nint main(){for(;;)pause();}' > pause.c;
diet -Os cc pause.c -o pause;
strip -s pause;
ls -al pause
python
직접 컴파일하고 싶지는 않지만 python
설치 한 경우 Linux에서이를 사용할 수 있습니다.
python -c 'while 1: import ctypes; ctypes.CDLL(None).pause()'
(참고 : exec python -c ...
현재 셸을 교체하는 데 사용 하면 PID 하나가 해제됩니다. 일부 IO 리디렉션을 통해 솔루션을 개선하여 사용하지 않는 FD를 해제 할 수도 있습니다. 이는 사용자에게 달려 있습니다.)
작동 방식 (제 생각) : ctypes.CDLL(None)
표준 C 라이브러리를로드하고 pause()
추가 루프 내 에서 함수를 실행합니다 . C 버전보다 효율적이지 않지만 작동합니다.
당신을위한 나의 추천 :
반복 수면을 유지하십시오. 이해하기 쉽고 휴대 성이 뛰어나며 대부분의 시간을 차단합니다.
답변
어쩌면 이것이 못생긴 것처럼 보이지만 실행을 cat
계속하고 입력을 영원히 기다리게 하지 않는 이유는 무엇입니까?
답변
TL; DR : sleep infinity
실제로 허용 된 최대 시간을 잠들게합니다.
왜 이것이 어디에도 문서화되어 있지 않은지 궁금 해서 GNU coreutils 에서 소스 를 읽으려고 노력했으며 대략 다음과 같이 실행됩니다.
strtod
‘무한대’를 배정도로 변환하려면 첫 번째 인수에서 C stdlib에서 사용하십시오 . 따라서 IEEE 754 배정도를 가정하면 64 비트 양의 무한대 값이seconds
변수에 저장됩니다 .- 호출은
xnanosleep(seconds)
( gnulib에서 발견 )이 차례를 발동에dtotimespec(seconds)
( 도 gnulib의 ) 변환하는 방법double
에struct timespec
. struct timespec
정수 부분 (초)과 소수 부분 (나노초)의 숫자 쌍입니다. 양의 무한대 를 정수 로 순전히 변환 하면 정의되지 않은 동작이 발생하고 (C 표준의 §6.3.1.4 참조) 대신로 절단됩니다TYPE_MAXIMUM (time_t)
.- 실제 값은
TYPE_MAXIMUM (time_t)
표준에 설정되어 있지 않습니다 (sizeof(time_t)
그렇지 않더라도). 예를 들어 최근 Linux 커널에서 x86-64를 선택하겠습니다.
이것은 TIME_T_MAX
Linux 커널에 있으며 다음과 같이 ( time.h
)로 정의 됩니다.
(time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
참고 time_t
인 __kernel_time_t
및 time_t
입니다 long
; LP64 데이터 모델이 사용되므로 sizeof(long)
8 (64 비트)도 사용됩니다.
결과 : TIME_T_MAX = 9223372036854775807
.
즉 sleep infinite
, 실제 절전 시간은 9223372036854775807 초 (10 ^ 11 년)입니다. 그리고 32 비트 리눅스 시스템의 경우 ( sizeof(long)
4 (32 비트)) : 2147483647 초 (68 년; 2038 년 문제 도 참조하십시오 ).
편집 : 분명히 nanoseconds
호출 된 함수는 직접 syscall이 아니라 OS 종속 래퍼 ( gnulib에 정의되어 있음 )입니다.
그 결과로 추가 단계가 있습니다 : 일부 시스템 HAVE_BUG_BIG_NANOSLEEP
인 true
수면 24 일립니다 다음 루프에서했다. 이것은 일부 (또는 모두?) Linux 배포판의 경우입니다. configure- time 테스트가 성공한 경우 ( source ) 이 랩퍼를 사용할 수 없습니다 .
특히, 24 * 24 * 60 * 60 = 2073600 seconds
(99999999 나노초 플러스); 그러나 지정된 총 절전 시간을 준수하기 위해 루프에서 호출됩니다. 따라서 이전 결론은 유효합니다.
결론적 으로 , 결과적인 실제 시간 경과가 휴대용이 아닌 경우에도 결과적인 수면 시간 은 무한하지만 모든 실제적인 목적을 위해 충분히 높을 수 없다. OS와 아키텍처에 따라 다릅니다.
원래 질문에 대답하기에, 이것은 분명히 충분하지만 어떤 이유로 ( 매우 자원이 제한된 시스템) 쓸모없는 여분의 카운트 다운 타이머를 피하고 싶다면 가장 적합한 대안은 cat
다른 답변에 설명 된 방법 을 사용하는 것입니다 .
답변
sleep infinity
가장 우아해 보이지만 때로는 어떤 이유로 작동하지 않습니다. 이 경우, 다른 차단 명령과 같은 시도 할 수 있습니다 cat
, read
, tail -f /dev/null
, grep a
등
답변
SIGSTOP 을 자신 에게 보내는 것은 어떻습니까?
SIGCONT가 수신 될 때까지 프로세스를 일시 정지해야합니다. 당신의 경우에는 : 결코.
kill -STOP "$$";
# grace time for signal delivery
sleep 60;
답변
왜 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;
}