Bash 스크립트의 와인을 통해 Ubuntu에서 실행 중인 Windows 명령줄 프로그램이 있습니다. Bash 스크립트는 기본적으로 다음과 같습니다.
wine myprogram.exe | while read line
do
# Process line
done
이제 myprogram.exe를 작성했기 때문에 가능한 한 빨리 데이터를 내보낸다는 것을 알았습니다. 내 프로그램이 while 루프가 처리할 수 있는 것보다 더 빠르게 데이터를 뱉어내는 경우 Bash while 루프가 데이터를 처리하는 방법을 설명할 수 있는 사람이 있나요? 커널 스케줄러가 너무 많은 데이터를 생성하는 경우 myprogram.exe를 절전 모드로 전환하는 숨겨진 마법이 있습니까? 누구나? 현재 나는 그것이 흑마법이 되는 쪽으로 기울고 있다.
답변1
첫째, 프로그램은 자체 출력 버퍼링을 수행할 수 있습니다. 이것은 때때로 "표준 입력 및 출력C에서 이 작업을 수행하는 라이브러리 구성 요소 이름 뒤에 "버퍼링"을 추가합니다. , 등에서 선언 putc
된 함수 fputs
입니다 . 그렇다면 일반적으로 몇 킬로바이트에 달하는 출력 버스트를 생성합니다(기본값은 출력이 터미널로 전달될 때 모든 줄 바꿈에서 버퍼를 플러시하는 것입니다).fprintf
stdio.h
어느 시점에서 프로그래머나 기본 라이브러리 함수가 호출됩니다.write
분명히. 이는 지정된 데이터를 파이프에 쓰도록 커널에 요청합니다. 커널은 데이터의 전부 또는 일부를 쓰기로 결정할 수 있습니다. 파일은 파이프이므로 커널은 데이터를 파이프의 버퍼에 복사합니다. 파이프 버퍼가 가득 차면 write
공간을 사용할 수 있을 때까지 시스템 호출이 차단됩니다. 즉, 프로그램(더 정확하게는 write
커널 수준 스레드가 여러 개인 경우 호출 스레드)은 호출이 write
반환될 때까지 실행을 재개하지 않습니다.
(이 경우에는 프로그램이 파이프의 파일 설명자를 다음으로 설정했을 가능성이 있지만 가능성은 낮습니다.비차단. 이 경우 커널이 데이터를 복사할 수 없다고 판단하면 시스템 write
호출은 0을 반환합니다. 이러한 비차단 시스템 호출을 수행하는 프로그램은 일반적으로 다음을 호출합니다.select
또는 poll
또는epoll
통신하는 파일 설명자 중 하나가 입력 또는 출력 준비가 될 때까지 루프를 차단합니다. )
시스템 호출 중에 프로그램이 차단된다는 사실은 스케줄링 알고리즘의 선택과 관련이 없습니다. 그 핵심은 무엇이든스케줄러구별하다준비해스레드에 CPU 시간이 주어질 수 있으며기다리다스레드이지만 할 수 없습니다. 스케줄러의 요점은 준비된 스레드를 선택하고 해당 스레드가 시스템 호출을 하거나(스레드를 대기 상태로 전환) 일부 비동기 이벤트가 발생할 때까지(실제로 프로세서가 실행되도록 하는 것입니다)방해하다). 시스템 호출을 처리하는 동안 이전에 차단된 스레드가 준비되었을 수 있습니다. 예를 들어 해당 스레드가 호출을 하고 있었고 write
이제 커널이 해당 호출에서 데이터를 전달할 수 있게 되었기 때문입니다. 준비된 스레드를 외부에서 차단할 수 있는 것들이 있습니다.일시정지 신호( SIGSTOP
). 스케줄러는 일종의준비 체크리스트다음에 예약할 스레드 결정: 준비된 스레드 목록(실제 스케줄러의 간단한 목록보다 훨씬 더 복잡한 경우가 많습니다).
답변2
파이프라인이라고 합니다. 이를 실행 man 7 pipe
하면 파이프라인이 어떻게 작동하는지 확인할 수 있습니다.
다음을 추가하도록 편집되었습니다. 즉, wine 명령의 출력은 버퍼에 수집됩니다. 버퍼가 가득 차서 와인이 더 많은 것을 쓰려고 하면 와인 프로세스가 커널에 의해 중지됩니다. 버퍼의 공간을 사용할 수 있게 되면(즉, while 루프가 버퍼에서 읽는 경우) 중지된 프로세스가 다시 활성화되어 계속 진행됩니다. 이것은 고전적인 제한된 버퍼 알고리즘이지만 Unix/Linux 세계에서는 종종 파이프라고 불립니다. 이는 매우 인기 있고 강력하므로 이에 대해 모두 배우는 것이 좋습니다.
답변3
아니요, 어둠의 마법은 없습니다(적어도 이번에는 아닙니다). 단지 출력 스트림의 캐시와 버퍼를 사용합니다.