2010-07-12 7 views
2

나는 open4 gem을 사용 중이며 생성 된 프로세스 stdout에서 읽는 데 문제가 있습니다. 내가 두 번째 프로그램을 실행하면프로그램이 stdin을 기다리는 중 왜 open4를 stdout에서 읽을 수 없습니까?

require 'open4' 

pid, stdin, stdout, stderr = Open4.popen4 'ruby test1.rb' 
p stdout.read(2) # 2 characters 

는 : 나는 루비 프로그램이, test1.rb :

print 'hi.' # 3 characters 
$stdin.read(1) # block 

과 같은 디렉토리에 다른 루비 프로그램, test2.rb

$ ruby test2.rb 

는 그냥 앉아 영원히 아무 것도 인쇄하지 않습니다. 왜 이런 일이 일어나고 그걸 막기 위해 무엇을 할 수 있습니까?

답변

2

같은 test2.rb 나는 이것에 test1.rb을 변경해야 할 수 있습니다. 나는 이유를 모른다. 기본적으로

print 'hi.' # 3 characters 
$stdout.flush 
$stdin.read(1) # block 
1

저는 전문가가 아닙니다.

API 문서의 첫 번째 장면에서 open4를 사용하는 순서는 다음과 같습니다. 먼저 stdin에 텍스트를 보내고 stdin을 닫고 stdout에서 텍스트를 읽습니다.

So. 이

require 'open4' 

pid, stdin, stdout, stderr = Open4.popen4 'ruby test1.rb' 
stdin.puts "something" # This line is important 
stdin.close # It might be optional, open4 might close itself. 
p stdout.read(2) # 2 characters 
2

, print 표준 출력에 또는 다른 파일에 루비 (루비 아래에있는 표준 C 라이브러리)의 버퍼에 기록 된 모든 것을. 다음 이벤트 중 하나가 발생하면 버퍼 내용이 OS로 전달됩니다.

  • 버퍼가 꽉 찼습니다.
  • stdout을 닫습니다.
  • 개행 시퀀스 (`\ n ')를 인쇄했습니다
  • flush을 명시 적으로 호출합니다.

다른 파일의 경우 도 ftell처럼 다른 경우에도 수행됩니다.

stdout을 버퍼링되지 않은 모드 ($stdout.sync = true)로 설정하면 버퍼가 사용되지 않습니다.

stderr는 기본적으로 버퍼링되지 않습니다. 버퍼링을하는 이유는 효율성입니다. 출력 데이터를 버퍼에 집계하면 많은 시스템 호출 (운영 체제 호출)을 저장할 수 있습니다. 시스템 호출은 매우 expensive입니다. 이들은 수백 또는 수천 개의 CPU 사이클을 사용합니다. 약간의 코드와 사용자 공간의 일부 버퍼를 사용하지 않으면 속도가 빨라집니다.

버퍼링에 대한 좋은 정보 : Why does printf not flush after the call unless a newline is in the format string?

관련 문제