고양이는 게으른 평가를 사용합니까? [복사]

고양이는 게으른 평가를 사용합니까? [복사]

예를 들어 파이프를 사용할 때

sudo cat /dev/sda | strings | less

SDA 장치의 문자열 내에서 이동할 수 있습니다. 그런데 sda 장치의 내용이 완전히 로드되어 고양이의 출력 스트림으로 출력됩니까? 아니면 프로그램이 cat의 출력을 요청할 때마다 개행 문자가 평가됩니까? (즉, 적은 호출기에서 j를 누릅니다)

답변1

이것은 HOW 나 작업 less보다는 HOW와 더 관련이 있습니다 .catstrings

cat명령은 데이터를 표준 출력으로 푸시하며, strings그 사이의 파이프 버퍼가 가득 차고 아무도 읽지 않는 한 차단됩니다. cat자체적으로 최소한의 버퍼링을 수행하며 파이프 버퍼는 일반적으로 작습니다.

에 대해서도 마찬가지입니다 strings. 결과 데이터가 읽히지 않으면 들어오는 데이터를 처리하고 cat차단 합니다.lessstrings

less해당 입력은 표시되는 데이터에서 앞뒤로 이동할 수 있도록 버퍼링됩니다. 다음 페이지로 스크롤하면 해당 버퍼에서 less더 많은 데이터를 읽습니다 . strings앞으로 스크롤하지 않으면 less제한된 양의 데이터만 읽힐 것이라고 생각합니다(그래서 앞으로 스크롤하지 않으면 차단됩니다) strings.cat

많은 양의 데이터가 파이프로 연결되면 less버퍼링에 많은 양의 메모리가 사용됩니다.만약에당신은 그것을 모두 읽기로 결정했습니다 less.

-B버퍼링에 사용되는 메모리 양을 64KB(또는 -b해당 옵션으로 지정한 크기) 로 제한하는 옵션이 있습니다 . 이러한 방식으로 버퍼 크기를 제한하면 지정된 버퍼 공간에 저장할 수 있는 것보다 더 많이 뒤로 스크롤하는 것을 방지할 수 있을 뿐만 아니라 less메모리 부족 없이 많은 양의 데이터를 읽을 수 있습니다 .

또한 man less시스템을 참조하십시오.

답변2

파이프에는 버퍼 공간이 제한되어 있으며 파이프 판독기(예 less: 예제)가 파이프에서 더 많은 데이터를 읽지 않으면 기록기는 버퍼를 채운 후 차단됩니다. 이는 strings명령 에 영향을 미치며 cat파이프가 가득 차면 명령을 차단합니다.

물론 이 cat명령으로는 sda 장치의 전체 내용을 메인 메모리로 읽어올 수는 없으므로 아직 읽지 않은 블록이 변경되면 cat변경된 내용을 보게 됩니다.

답변3

그리고 cat대부분의 strings유사한 유틸리티에서는 한 번에 약간의 입력을 읽고 처리한 다음 더 많은 입력을 읽는 등의 작업을 수행합니다. 따라서 귀하의 경우에는 표시된 내용과 전송되는 내용 중 일부만 읽혀집니다 cat.less

더 자세히 살펴보면 기본 작업은 다음 cat과 같습니다.

  • 몇 킬로바이트의 메모리가 버퍼로 사용되도록 예약되어 있습니다.
  • 사용할 수 있는 입력이 더 많지만 다음과 같습니다.
    • 최대 N바이트의 입력을 버퍼로 읽습니다. (이전 사이클에 기록된 데이터를 덮어쓰게 됩니다.)
    • 출력에 버퍼 내용을 씁니다.

출력을 복사할 위치가 있을 때까지 쓰기 작업이 차단됩니다. 파이프가 출력할 때 파이프 자체는 커널에서 약간의 메모리를 소비합니다.파이프 버퍼. 가득 차면 cat파이프에 쓰기를 시도하면 공간을 사용할 수 있을 때까지 쓰기 시도가 차단됩니다. 파이프의 읽기 측 프로세스가 일부 데이터를 읽을 때 파이프 버퍼에 공간이 있을 수 있습니다.

이 프로그램은 전체 입력을 복사하지 않고 선택한 부분만 복사한다는 점을 제외하면 strings와 동일한 방식으로 작동합니다 .cat

less프로그램은 약간 다르게 작동합니다. 읽은 모든 내용을 메모리에 보관합니다. 버퍼를 재활용하지 않고, 더 많은 입력이 계속 들어오는 한 계속해서 버퍼를 증가시킵니다. 그러나 읽기 부분은 less필요할 때만 데이터를 읽는다는 점에서 비슷합니다. 표시된 마지막 줄과 읽을 것으로 예상되는 줄까지만 읽습니다.

따라서 를 실행하면 sudo cat /dev/sda | strings | less읽혀지는 내용은 /dev/sda다음과 같습니다.

  • less데이터가 표시되거나 스크롤되어 지나갔습니다.
  • less읽었지만 아직 표시되지 않은 데이터는 최대 몇 kB입니다.
  • strings와 사이의 파이프 버퍼는 최대 몇 kB입니다 less.
  • 메모리 용량은 최대 몇 kB까지 가능합니다 strings.
  • cat와 사이의 파이프 버퍼는 최대 몇 kB입니다 strings.
  • 메모리 용량은 최대 몇 kB까지 가능합니다 cat.

시스템 호출을 추적하여 각 프로그램이 데이터를 읽고 쓰는 시기를 관찰할 수 있습니다.

sudo strace -e read,write -o cat.strace cat /dev/sda | strace -e read,write -o cat.strace strings | strace -e read,write -o less.strace less

그리고 *.strace파일을 보세요. 예를 들어 where is 를 사용하거나 프로세스 ID를 사용하여 cat파일 오프셋을 확인하여 읽은 데이터의 양을 확인할 수도 있습니다 .lsof -p1234head /proc/1234/fdinfo/01234cat

1 기본 텍스트 처리 유틸리티에서 주요 예외는 sort전체 입력을 읽을 때까지 출력을 내보낼 수 없다는 것입니다. 아는 한 출력의 첫 번째 줄은 도달한 입력의 마지막 줄일 가능성이 높습니다.

답변4

일부 시스템(예: MS-Dos)에서는 첫 번째 명령의 출력을 파일에 복사한 다음 두 번째 명령을 실행하여 해당 파일에서 읽는 방식으로 파이프가 구현됩니다. 유닉스는 이런 일을 하지 않는다.

Unix에서는 생산 라인과 같습니다. 각 단계는 동시에 작동하여 입력을 읽고 출력을 생성합니다. 프로세스 A가 프로세스 B가 소비하는 것보다 빠르게 생산하면 프로세스 A와 B 사이에 재고가 축적됩니다. 인벤토리가 너무 많으면(½KiB ~ 4KiB) 프로세스 A가 일시 중지됩니다. B가 처리할 재고가 없으면 B는 일시 중지됩니다. 재고 수준을 낮게 유지하기 위해 프로세스가 일시 중지되거나 일시 중지 해제됩니다.

이 프로그램의 코드는 그것에 대해 신경 쓰지 않습니다. 단지 입력을 읽고 출력을 씁니다. 데이터를 사용할 수 있기 전에 읽으려고 하거나 다음 프로세스가 준비되기 전에 쓰려고 하면 운영 체제는 준비될 때까지 이를 일시 중지합니다.

더 이상 읽을 내용이 없고 더 이상 읽고 있는 내용도 없으면 리더는 파일 끝을 수신하고 종료됩니다. 그러면 다음 프로세스에서 파일 끝이 트리거됩니다.

관련 정보