programing

Bash: 무한 절전(무한 차단)

bestprogram 2023. 4. 12. 23:06

Bash: 무한 절전(무한 차단)

용 i i i i를 쓴다.startx의 X를 하는 X를 합니다..xinitrc 제제 my my . ..xinitrc윈도우 매니저를 시작합니다./usr/bin/mywmWM을WM을 (다른 WM을 테스트하기 위해) WM의 .xinitrcEOF를 사용하다 제가 에 이렇게 ..xinitrc:

while true; do sleep 10000; done

이렇게 하면 내 WM을 죽여도 X가 종료되지 않는다.이제 제 질문은 어떻게 하면 반복수면 대신 무한수면을 취할 수 있을까요?스크립트를 정지시키는 명령어가 있나요?

sleep infinity고양이 학대 없이 정확히 행동할 수 있습니다.

tail하지 않다

하고 이해하기 따라하기 틀린 .모든 일에는 짧고, 이해하기 쉽고, 따라하기 쉽고, 완전히 틀린 답이 있다.서 ★★★★tail -f /dev/null

로 보면strace tail -f /dev/null이 솔루션은 차단과는 거리가 멀다는 것을 알게 될 것입니다. 더 거야sleep like like like like like like like like like like like, like like like solution the the the the the the the the the the the the the the the the the the the the the the the the the the the 와 같은 귀중한을 사용하기 에, 질문의 해결 방법.inotify시스템.또, 에 기입하는 다른 프로세스/dev/null 만들다tail(Ubuntu64 16.10은 syscall을 사용합니다).

차단 명령어에 대한 질문입니다.

아쉽게도 그런 건 없어요.

셸을 사용하여 직접 아카이브하는 방법을 알 수 없음을 확인.

모든 것(짝수까지)sleep infinity이(가 될 수 있습니다.)이(가) 일부 신호에 의해 중단될 수 있습니다.되지 않도록 '돌아가다'에서 했던 루프로 .sleep (Linux의 : (Linux의 경우)/bin/sleep입니다.strace sleep infinity)따라서 할 수 있는 최선의 방법은 다음과 같습니다.

while :; do sleep 2073600; done

해 주세요.sleep으로는 24일보다 이것은 다음을 의미합니다.블로킹이 아니라 매우 천천히 루프하고 있습니다.그럼 이 루프를 외부로 이동시키면 어떨까요?

... 이름 없는 '아저씨'는 꽤 갈 수 있다fifo

프로세스에 신호가 전송되지 않는 한 실제로 차단할 수 있습니다. 사용법bash 4와 1, PID x 2µ x 1fifo:

bash -c 'coproc { exec >&-; read; }; eval exec "${COPROC[0]}<&-"; wait'

할 수 .strace★★★★★★★★★★★★★★★★:

strace -ff bash -c '..see above..'

어떻게 구성되었음

read입력 데이터가 없는 경우 차단합니다(다른 답변 참조). 「」, 「」는ttystdin할 때 에 좋은 는 보통 사용자가 로그아웃할 때 닫히기 때문에 좋은 소스가 아닙니다., ,, 이, 이, 데, 데, 데, the, the, the, the, the, the, the, the, the, the, the, the, the, the, the, the, the ,tty않아 지지않않않않

★★★★★★★★★★★★★★★★★를 만들다read, 기다리다, 기다리다, 기다리다, 거요.fifo(In)bash 4 명령어를 할 수 .fifocoprocread은 우리의 (그것은)coproc는 종료되었습니다을 사용하다도 이것은 와 1개의 PID를 오픈 .fifo.

이 ''인 배리언트'fifo

이 것을 굳이 fifo

mkfifo "$HOME/.pause.fifo" 2>/dev/null; read <"$HOME/.pause.fifo"

하지 않는 엉성하지만, 이 루프를 다시 할 수 .fifo , 원하는 만큼 만들어 .read를 사용하여 합니다.touch "$HOME/.pause.fifo"(읽기 대기 상태가 여러 개일 경우 모두 한 번에 종료됩니다).

Linux 를 합니다.pause()

커널 콜이 이 콜은 Linux 커널 콜입니다.pause()델이 원하는 것을 실현합니다.(신호가 도착할 때까지) 영원히 기다립니다.그러나 아직 이를 위한 사용자 공간 프로그램은 없습니다.

C

이러한 프로그램을 만드는 것은 쉽다.에서는, 「Linux」라고 하는 매우 합니다.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

을 하고 컴파일이 있는 pythonLinux 서 linux linux linux linux linux linux linux linux linux linux linux 。

python -c 'while 1: import ctypes; ctypes.CDLL(None).pause()'

사용(주: 사용)exec python -c ...PID가 1로 설정되어 있습니다. IO 수 FD를할 수 .을 사용하다

구내내내내내 ( ( 。ctypes.CDLL(None) C 하여 C 를 실행합니다.pause()이치c c. c. c. c.

추천할 것은 다음과 같습니다.

루핑 수면 상태로 있어이해하기 쉽고 휴대성이 뛰어나며 대부분의 경우 차단됩니다.

흉할 왜 뛰지 거죠?cat릴을릴릴릴릴릴릴릴릴릴릴릴릴릴?

GNU , TL;DR: GNU coreutiles "9"sleep infinityLinux 스 linux linux linux linux linux linux linux 。이전에는 (및 다른 시스템에서는) 실제로 허용되는 최대 시간까지 sleep 상태로 이행하는 것이 가능했습니다.이것은 유한합니다.


왜 이것이 어디에도 문서화되어 있지 않은지 궁금해서 GNU coreutils에서 소스를 읽어보니 대략 다음과 같은 작업이 실행된다는 것을 알 수 있었습니다.

  1. 첫 번째 인수에 C stdlib에서 사용하여 'infinity'를 2배 정밀도 값으로 변환합니다.따라서 IEEE 754의 2배 정밀도를 가정하면 64비트 양의 무한대 값이seconds★★★★★★ 。
  2. xnanosleep(seconds)(gnulib에서 발견됨) 이것은 차례로dtotimespec(seconds)(또한 gnulib)에서 변환하다double로로 합니다.struct timespec.
  3. struct timespec 는 정수 부분(초단위)과 소수 부분(나노초단위)의 단순한 숫자 쌍입니다.의 무한대를 정수로 쉽게 변환하면 정의되지 않은 동작이 발생하므로(C 표준의 제6.3.1.4절 참조), 대신 다음과 같이 잘립니다.TYPE_MAXIMUM(time_t).
  4. 「」의 .TYPE_MAXIMUM(time_t) 않습니다(심지어 표준에는 설정되어 있지 않습니다).sizeof(time_t)Linux x86-64 입니다.

은 것은입니다.TIME_T_MAXLinux 커널에서 다음과 같이 정의()time.h됩니다.

(time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)

:time_t__kernel_time_t ★★★★★★★★★★★★★★★★★」time_tlong에 ; LP64 데이터 모델이 사용됩니다.sizeof(long)8(64번)ㄹ 것이다.

다음과 같이 됩니다.TIME_T_MAX = 9223372036854775807.

즉, 음, 음, 음, 음, 음, that이다.sleep infinite9223372036854775807(10^11)이다. 시스템(32비트 Linux 시스템의 경우sizeof(long)는 4(32비트): 2147483647초(68년, 「2038년 문제」도 참조).


편집: 분명히nanoseconds호출된 함수는 직접 syscall이 아니라 OS 의존 래퍼(gnulib에서도 정의됨)입니다.

그 결과 추가 단계가 있습니다. 일부 시스템에서는HAVE_BUG_BIG_NANOSLEEPtruesleep은 24일로 잘린 후 루프로 호출됩니다.이것은 일부(또는 전체)의 경우입니다.Linux 디스트로스설정 시간 테스트(소스)가 성공했을 경우, 이 래퍼는 사용되지 않는 경우가 있습니다.

은 「 」, 「 」입니다.24 * 24 * 60 * 60 = 2073600 seconds(단, 99999999999). 단, 이것은 지정된 총 sleep 시간을 유지하기 위해 루프에서 호출됩니다.따라서 이전 결론은 여전히 유효하다.


결론적으로 sleeve 시간은 무한하지 않지만 실제 경과 시간은 이동할 수 없는 경우에도 모든 실용적인 목적에 충분히 높습니다.이는 OS와 아키텍처에 따라 달라집니다.

원래의 질문에 대답하면, 이것은 분명히 충분합니다만, 어떠한 이유로(자원이 매우 제한된 시스템) 불필요한 카운트다운 타이머를 정말로 피하고 싶다면, 가장 올바른 대안은,cat다른 답변에서 설명된 방법을 참조하십시오.

편집: 최신 GNU coreutils 버전은 다음 버전을 사용하려고 합니다.pause시스콜이전 인수는 Linux(및 BSD)에서 이러한 새로운 버전을 대상으로 하는 경우에는 더 이상 유효하지 않습니다.


휴대성

이는 중요하고 유효한 문제입니다.

  • sleep infinityPOSIX에서는 고려되지 않는 GNU coreutils 확장입니다.GNU의 실장에서는, 다음과 같은 「fancy」구문도 서포트되고 있습니다.sleep 1h 5.2s에서는, 을 사용할 수(예를 들면, POSIX 의 경우).sleep 0.5는 허용되지 않습니다).
  • 일부 호환 구현: GNU coreutils, FreeBSD(최소 버전 8.2부터), Busybox(옵션으로 컴파일해야 함)FANCY_SLEEP ★★★★★★★★★★★★★★★★★」FLOAT_DURATION를 참조해 주세요.
  • strtod와 POSIX에 「C」POSIX」의 경우).strtod("infinity", 0)는, C99 준거 실장에서는 항상 유효합니다( 「7.20.1.3」 참조).

sleep infinity 블로킹명령어, 를 들어 '블럭킹' , 예를 들어 '블럭킹명령어, 를 들어 '블럭킹 명령어, 예를 들어 '블럭킹 명령어, 를 들어 '블럭킹명령어'를 사용할 수 .cat,read,tail -f /dev/null,grep asyslog.

이유를 하겠습니다.sleep infinityjp48의 답변도 도움이 됩니다.

한 것: 「」를 으로써: 「」를 지정합니다.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/xstrod.c에 따르면,xstrtod()argv[i]한다.*s하여 변환함수를 사용합니다.cl_strtod().

cl_strtod()

coreutils/lib/cl-strod.c에서 알 수 있듯이cl_strtod()합니다.strtod().

strtod()

★★★★★★★에 의하면man 3 strtod,strtod()을 타입의 합니다.double에는 manpage라고 쓰여 있습니다.

(의 초기 부분) 문자열의 예상 형식은 ... 또는 (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;
  }

thus따는INF ★★★★★★★★★★★★★★★★★」INFINITYHUGE_VAL.

HUGE_VAL

N1570을 C의 스탠다드로 합니다. HUGE_VAL,HUGE_VALF ★★★★★★★★★★★★★★★★★」HUGE_VALL7.에 정의되어 있습니다.

(Macro)
    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()

는 타입의 합니다.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;
}

SIGSTOP을 자신에게 보내는 건 어때?

그러면 SIGCONT가 수신될 때까지 프로세스가 일시 정지됩니다.그건 당신 경우죠. 절대요.

kill -STOP "$$";
# grace time for signal delivery
sleep 60;

나는 최근에 이것을 해야 할 필요가 있었다.외부 프로그램을 호출하지 않고 bash를 영원히 sleep 상태로 만들 수 있는 다음 기능을 생각해 냈습니다.

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 || :
}

메모: 이전에 파일 디스크립터를 매번 열고 닫는 버전을 올렸습니다만, 일부 시스템에서는 1초에 수백 번 이 작업을 하면 최종적으로 행업하는 것을 발견했습니다.따라서 새로운 솔루션은 함수에 대한 호출 사이에 파일 기술자를 유지합니다.어차피 배쉬가 치울 거야

이것은 /bin/sleep과 마찬가지로 호출할 수 있으며 요청된 시간 동안 sleep 상태가 됩니다.매개 변수 없이 호출되면 영원히 중단됩니다.

snore 0.1  # sleeps for 0.1 seconds
snore 10   # sleeps for 10 seconds
snore      # sleeps forever

여기 내 블로그에 너무 자세한 내용이 적혀있어

이 접근방식에서는 프로세스를 존속시키기 위한 리소스가 소비되지 않습니다.

while :; do :; done & kill -STOP $! && wait

내역

  • while :; do :; done &.
  • kill -STOP $!합니다.
  • wait프로세스를 되어 있기 때문입니다.이 프로세스는 영원히 차단됩니다.그 전에 백그라운드 프로세스가 중지되었기 때문입니다.

메모들

  • 는 스크립트 파일 내에서만 작동합니다.

매니저를 새로운 매니저를 .--replace ★★★★★★★★★★★★★★★★★」-replace가능한 경우.

while :; do read; done

아이의 수면 과정을 기다릴 필요가 없습니다.

언급URL : https://stackoverflow.com/questions/2935183/bash-infinite-sleep-infinite-blocking