Điều gì làm cho một quá trình Unix chết với Broken pipe?


30

Dưới đây là một số tùy chọn tôi nghĩ ra, không chắc cái nào đúng.

  1. Có lỗi đọc I / O từ đường ống.
  2. Quá trình viết đến đầu kia của ống chết với một thất bại.
  3. Tất cả các quy trình có thể ghi vào đường ống đã đóng nó.
  4. Bộ đệm ghi của đường ống đã đầy.
  5. Các đồng đẳng đã đóng hướng khác của ống song công.
  6. Viết thất bại vì không có quá trình có thể đọc từ đường ống.
  7. Một cuộc gọi hệ thống đã trả về lỗi EPIPE và không có trình xử lý lỗi nào được cài đặt.

Câu hỏi của bạn là gì? Bạn đang hỏi cái nào trong số đó là chính xác, hoặc nếu có bất kỳ điều gì khác có thể gây ra đường ống bị vỡ?
EightBitTony

@EightBitTony Điều nào trong số này là đúng
siamii

Câu trả lời:


38

Một quá trình nhận được SIGPIPE khi nó cố ghi vào một đường ống (có tên hoặc không) hoặc ổ cắm loại SOCK_STREAM không còn đầu đọc.

Đó thường là hành vi muốn. Một ví dụ điển hình là:

find . | head -n 1

Bạn không muốn findtiếp tục chạy một khi headđã chấm dứt (và sau đó đóng bộ mô tả tệp duy nhất mở để đọc trên đường ống đó).

Các yeslệnh thường dựa vào đó tín hiệu chấm dứt.

yes | some-command

Sẽ viết "y" cho đến khi một số lệnh kết thúc.

Lưu ý rằng không chỉ khi thoát lệnh, đó là khi tất cả người đọc đã đóng fd đọc của họ vào đường ống. Trong:

yes | ( sleep 1; exec <&-; ps -fC yes)
      1 2       1        0

Sẽ có 1 (subshell), sau đó 2 (subshell + ngủ), sau đó 1 (subshell) rồi 0 fd đọc từ ống sau khi subshell đóng rõ ràng stdin của nó và khi đó yessẽ nhận được SIGPIPE.

Ở trên, hầu hết các shell sử dụng một pipe(2)thời gian ksh93sử dụng a socketpair(2), nhưng hành vi là như nhau về vấn đề đó.

Khi một quá trình bỏ qua các SIGPIPE, cuộc gọi hệ thống chữ viết (nói chung write, nhưng có thể pwrite, send, splice...) trở lại với một EPIPElỗi. Vì vậy, các quy trình muốn xử lý đường ống bị hỏng theo cách thủ công thường bỏ qua SIGPIPE và thực hiện hành động khi xảy ra lỗi EPIPE.


14

(6)

Viết thất bại vì không có quá trình có thể đọc từ đường ống.

Mặc dù trừ khi bạn sao chép mô tả và ngã ba, chỉ có thể có một quy trình để bắt đầu: nói chung một đường ống có một đầu đọc và một đầu ghi và khi một trong số chúng đóng kết nối, đường ống không còn tồn tại. Nếu bạn đang sử dụng một đường ống có tên, bạn có thể tạo nhiều kết nối (nối tiếp) với nó, nhưng mỗi đường dẫn đại diện cho một đường ống mới theo nghĩa này. Vì vậy, một "đường ống" đến một luồng hoặc quá trình đồng nghĩa với một mô tả tập tin.

Từ man 7 pipe:

Nếu tất cả các mô tả tập tin liên quan đến đầu đọc của một đường ống đã bị đóng, thì một ghi (2) sẽ tạo ra tín hiệu SIGPIPE được tạo cho quá trình gọi. Nếu quá trình gọi bị bỏ qua tín hiệu này, thì ghi (2) không thành công với lỗi EPIPE.

Vì vậy, một "ống vỡ" là cho người viết EOF là gì đối với người đọc.


0

Một đường ống bị vỡ xảy ra khi quá trình đọc thoát ra trước quá trình viết. Vì vậy, tôi sẽ đi với (6)


2
Có thể có một số quy trình đọc hoặc ghi vào một đường ống, và quá trình tương tự có thể là đọc và viết. Ngoài ra, nó không phải là thoát, mà là về việc đóng bộ mô tả tệp.
Stéphane Chazelas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.