2014-03-03 8 views
1

많은 줄이있는 텍스트 파일이 있습니다. 이 파일을 줄 단위로 처리하고 줄을 인쇄하는 간단한 OCaml 프로그램을 작성하고 싶습니다.OCaml - 치명적 오류 : 예외 '|'를 사용할 때 Sys_error ("깨진 파이프"). head` 출력이 많습니다.

이 프로그램을 작성하기 위해 필자는 더 적은 수의 줄이있는 작은 파일을 작성하여 프로그램이 더 빨리 실행되도록 완료합니다. 여기

$ wc -l input/master 
214745 input/master 
$ head -50 input/master > input/small-master 

내가 쓴 간단한 상용구 filter.ml 프로그램입니다 :

그것은 명령 행 인수로 입력 파일의 위치를 ​​취
open Core.Std;; 
open Printf;; 
open Core.In_channel;; 

if Array.length Sys.argv >= 2 then begin 
    let rec process_lines ?ix master_file = 
    let ix = match ix with 
     | None -> 0 
     | Some x -> x 
    in 
    match input_line master_file with 
    | Some line -> (
     if ix > 9 then printf "%d == %s\n" ix line; 
     process_lines ~ix:(ix+1) master_file 
    ) 
    | None -> close master_file 
    in 
    let master_file = create Sys.argv.(1) in 
    process_lines master_file 
end 

가이 파일을 읽기 위해 파일 핸들을 생성하고 재귀 함수를 호출 process_lines이 파일 핸들을 인수로 사용합니다.

process_lines은 파일 핸들에서 줄 단위로 읽는 줄 번호를 계산하기 위해 선택적 인수 ix을 사용합니다. process_lines는 단순히 file_handle에서 읽은 행을 표준 출력으로 인쇄합니다.

, 나는 작은 입력 파일 및 파이프에서 프로그램을 실행할 때 다음, 리눅스 head 명령 모두에 출력이 잘 작동 : 나는 큰 파일 I에서 프로그램을 실행할 때,

$ ./filter.native input/small-master |head -2 
10 == 1000032|BINCH JAMES G|4|2012-11-13|edgar/data/1000032/0001181431-12-058269.txt 
11 == 1000032|BINCH JAMES G|4|2012-12-03|edgar/data/1000032/0001181431-12-061825.txt 

을 그리고 나는 파이프 (이 경우 head 명령)의 독자가이 경우 파이프의 작가 이전에 (내 OCaml의 프로그램을 종료 할 때 같은 깨진 파이프 오류가 발생할 것을 알게

$ ./filter.native input/master |head -2 
10 == 1000032|BINCH JAMES G|4|2012-11-13|edgar/data/1000032/0001181431-12-058269.txt 
11 == 1000032|BINCH JAMES G|4|2012-12-03|edgar/data/1000032/0001181431-12-061825.txt 
Fatal error: exception Sys_error("Broken pipe") 
Raised by primitive operation at file "pervasives.ml", line 264, characters 2-40 
Called from file "printf.ml", line 615, characters 15-25 
Called from file "find.ml", line 13, characters 21-48 
Called from file "find.ml", line 19, characters 2-27 

: 깨진 파이프 오류가 표시) 님이 글을 작성했습니다. 지. 그렇다면 내가 tail 명령을 독자로 사용하면 결코 그런 오류를 내지 않을 것입니다.

그러나 파일 수가 줄었 으면 broken-pipe 오류가 발생하지 않은 이유는 무엇입니까?

답변

2

깨진 파이프 신호는 유닉스 디자인의 기본 부분입니다. b이 작은 양의 데이터 만 읽는 파이프 라인이있는 a | b이있는 경우 b이 필요한 모든 것을 읽은 후에 a은 시간을 낭비하지 않아야합니다. 이런 일이 일어나게하려면 Unix는 깨진 파이프 신호를 아무에게도 읽지 않는 파이프에 쓰는 프로세스로 보낸다. 보통의 경우, 이로 인해 프로그램이 자동 종료되고 (즉, 프로그램이 종료됩니다), 이는 사용자가 원하는 것입니다.

이 가상의 예에서는 몇 줄을 읽은 후 b이 종료되어 아무도 파이프를 읽지 못함을 의미합니다. 다음 번에 a이 더 많은 출력을 쓰려고하면 깨진 파이프 신호가 전송되어 종료됩니다.

귀하의 경우에는 a이 귀하의 프로그램이고 bhead입니다.

OCaml 런타임이 신호를 감지하고 자동 종료하지 않는 것처럼 보입니다. 이 결함을 고려해 보거나 신호가 프로그램을 종료 할 때마다 알면 좋습니다. 가장 좋은 방법은 신호를 직접 잡아서 자동으로 종료하는 것입니다.

작은 파일에서 발생하지 않는 이유는 전체 출력이 파이프에 맞기 때문입니다. (파이프는 64K 바이트 정도의 버퍼를 나타냅니다.) 당신의 프로그램은 단지 데이터를 쓰고 빠져 나간다. 프로그램이 독자가없는 파이프에 쓰려고하는 충분한 시간이 없습니다.