`dmesg | head`에서 (어떻게) 10줄의 출력 후에 dmesg가 종료됩니까? [복사]

`dmesg | head`에서 (어떻게) 10줄의 출력 후에 dmesg가 종료됩니까? [복사]

다음 명령을 실행하면:

dmesg | head -n 10

나는 OS가 dmesg10줄을 읽은 후 일종의 신호를 다시 보낸다고 가정합니다. head어떻게 작동하나요? head커널에 무엇을 말해주는가?

이는 일반적인 "클린" 중지이므로 프로그램 종료와 다릅니다.

답변1

이는 운영 체제 버퍼와 10번째와 11번째 쓰기 사이의 타이밍에 따라 다릅니다 dmesg.

head10줄을 쓴 후 종료되고 dmesg수신됩니다.SIGPIPE 신호파이프에 계속 쓰는 경우.

운영 체제 버퍼에 따라 일반적으로 dmesg10개 이상의 라인이 사용되기 전에 기록됩니다.head

head10개 이상의 행이 사용되었는지 확인하려면 다음을 사용할 수 있습니다.

strace -f sh -c 'dmesg | head -n 10'

head( 프로세스를 보고 read시스템 호출 횟수를 계산합니다.)

쓰기 속도에 미치는 영향을 확인하세요.

strace -f sh -c "perl -le '$|++;print 1 while 1' | head -n 10"

답변2

보세요write()함수에 대한 POSIX 사양:

다음과 같은 경우 이 write()기능이 실패합니다 .

… 프로세스에서 읽을 수 있도록 열리지 않거나 한쪽 끝만 열려 있는 파이프 또는 FIFO에 쓰기를 시도합니다. SIGPIPE 신호도 스레드로 전송되어야 합니다.

따라서 이벤트 순서는 다음과 같습니다.

  1. 프로세스가 head종료됩니다. 이로 인해 표준 입력(파이프의 한쪽 끝)을 포함하여 열려 있는 모든 파일 설명자가 닫힙니다.

  2. 프로세스 는 파이프의 다른 쪽 끝인 표준 출력을 dmesg호출합니다 .write()

  3. 이로 인해 SIGPIPE가 프로세스에 전달됩니다 dmesg.

  4. dmesgSIGPIPE에는 특별한 처리가 없으므로 프로세스를 종료하는 기본 작업이 적용됩니다.

SIGPIPE 신호의 동작을 변경하여 실험할 수 있습니다. 예를 들어 파이프는 한 줄을 인쇄한 후 종료됩니다.

$ yes | head -1
y
$

그러나 SIGPIPE를 무시하면 종료되지 않습니다.

$ trap '' PIPE
$ yes | head -1
y

이 시점에서 yes프로세스는 여전히 파이프에 쓰기를 시도하고 있지만 EPIPE로 인해 쓰기가 실패합니다.

답변3

head폐쇄표준 입력10줄을 인쇄한 후. 그런 다음 dmesg감지되었습니다.표준 출력닫고 종료합니다.

보다 정확하게는 호출에서 오류가 dmesg수신됩니다 .EPIPEwrite표준 출력.

~에서dmesg.c소스 코드는 여기에 있습니다:https://github.com/karelzak/util-linux/blob/v2.27.1/sys-utils/dmesg.c#L654-L659

rc = fwrite(p, 1, len, out) != len;
if (rc != 0) {
    if (errno != EPIPE)
        err(EXIT_FAILURE, _("write failed"));
    exit(EXIT_SUCCESS);
}

관련 정보