Khi true
thoát ra, phía đọc của ống được đóng lại, nhưng yes
tiếp tục cố gắng ghi vào bên viết. Tình trạng này được gọi là "đường ống bị hỏng" và nó khiến kernel gửi SIGPIPE
tín hiệu đến yes
. Vì yes
không có gì đặc biệt về tín hiệu này, nó sẽ bị giết. Nếu nó bỏ qua tín hiệu, write
cuộc gọi của nó sẽ thất bại với mã lỗi EPIPE
. Các chương trình làm điều đó phải được chuẩn bị để thông báo EPIPE
và ngừng viết, nếu không chúng sẽ đi vào một vòng lặp vô hạn.
Nếu bạn làm strace yes | true
1, bạn có thể thấy kernel chuẩn bị cho cả hai khả năng:
write(1, "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 4096) = -1 EPIPE (Broken pipe)
--- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=17556, si_uid=1000} ---
+++ killed by SIGPIPE +++
strace
đang xem các sự kiện thông qua API trình gỡ lỗi, lần đầu tiên thông báo cho nó về việc gọi lại hệ thống có lỗi và sau đó là về tín hiệu. Từ yes
quan điểm 's, tuy nhiên, các tín hiệu xảy ra đầu tiên. (Về mặt kỹ thuật, tín hiệu được phân phối sau khi nhân trả lại quyền điều khiển cho không gian người dùng, nhưng trước khi thực hiện thêm bất kỳ lệnh máy nào, do đó, write
chức năng "trình bao bọc" trong thư viện C không có cơ hội đặt errno
và quay lại ứng dụng.)
1 Đáng buồn thay, strace
là Linux cụ thể. Hầu hết các Unix hiện đại đều có một số lệnh làm một cái gì đó tương tự, nhưng nó thường có một tên khác, nó có thể không giải mã triệt để các đối số tòa nhà và đôi khi nó chỉ hoạt động cho root.
yes | tee >(true) >/dev/null
sẽ làm như bạn mong đợi, btw, nhưtee
tiếp tục cho đến khi tất cả các nhà văn đã chết, vì vậy việctrue
thoát ra sẽ không phá vỡ hoàn toàn.