สิ่งที่ทำให้กระบวนการ Unix ตายด้วย Broken pipe?


30

นี่คือตัวเลือกบางอย่างที่ฉันคิดว่าไม่แน่ใจว่าเป็นตัวเลือกที่เหมาะสมหรือไม่

  1. มีข้อผิดพลาด I / O ที่อ่านจากไปป์
  2. กระบวนการเขียนไปยังปลายอีกด้านหนึ่งของท่อตายด้วยความล้มเหลว
  3. กระบวนการทั้งหมดที่สามารถเขียนไปยังไพพ์ได้ปิดลง
  4. บัฟเฟอร์การเขียนของไพพ์เต็ม
  5. เพียร์ได้ปิดทิศทางอื่น ๆ ของท่อดูเพล็กซ์
  6. การเขียนล้มเหลวเนื่องจากไม่มีกระบวนการที่สามารถอ่านได้จากไปป์
  7. การเรียกระบบส่งคืนข้อผิดพลาด EPIPE และไม่มีการติดตั้งตัวจัดการข้อผิดพลาด

คำถามของคุณคืออะไร คุณกำลังถามว่าสิ่งใดที่ถูกต้องหรือหากมีสิ่งอื่นใดที่สามารถทำให้ท่อแตกได้
EightBitTony

@EightBitTony ข้อใดถูกต้อง
siamii

คำตอบ:


38

กระบวนการได้รับ SIGPIPE เมื่อพยายามเขียนไปที่ไพพ์ (ตั้งชื่อหรือไม่) หรือซ็อกเก็ตประเภท SOCK_STREAM ที่ไม่มีผู้อ่านเหลืออยู่

เป็นพฤติกรรมที่ต้องการโดยทั่วไป ตัวอย่างทั่วไปคือ:

find . | head -n 1

คุณไม่ต้องการfindให้ทำงานต่อไปเมื่อheadถูกยกเลิก (แล้วปิดไฟล์ descriptor เพียงไฟล์เดียวที่เปิดสำหรับการอ่านบนไพพ์นั้น)

yesคำสั่งมักจะอาศัยสัญญาณว่าจะยุติ

yes | some-command

จะเขียน "y" จนกว่าคำสั่งบางคำสั่งจะถูกยกเลิก

โปรดทราบว่ามันไม่เพียง แต่เมื่อคำสั่งออกเท่านั้น แต่เมื่อผู้อ่านทั้งหมดปิดการอ่าน fd ไปยังไพพ์ ใน:

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

จะมี 1 (subshell) จากนั้น 2 (subshell + sleep) จากนั้น 1 (subshell) จากนั้น 0 fd ที่อ่านจากไปป์หลังจากที่ subshell ปิด stdin อย่างชัดเจนและนั่นคือเมื่อyesจะได้รับ SIGPIPE

ข้างต้นเชลล์ส่วนใหญ่ใช้ a pipe(2)ขณะที่ksh93ใช้ a socketpair(2)แต่พฤติกรรมนั้นเหมือนกันในเรื่องนั้น

เมื่อกระบวนการละเว้น SIGPIPE ที่โทรระบบการเขียน (โดยทั่วไปwriteแต่อาจจะpwrite, send, splice... ) ผลตอบแทนที่มีEPIPEข้อผิดพลาด ดังนั้นกระบวนการที่ต้องการจัดการไปป์ที่แตกด้วยตนเองจึงมักจะมองข้าม SIGPIPE และดำเนินการตามข้อผิดพลาด EPIPE


14

(6)

การเขียนล้มเหลวเนื่องจากไม่มีกระบวนการที่สามารถอ่านได้จากไปป์

แม้ว่าคุณจะทำซ้ำ descriptors และ fork แต่มีเพียงกระบวนการเดียวเท่านั้นที่เริ่มต้นด้วย: โดยทั่วไปไพพ์จะมีตัวอ่านหนึ่งตัวและหนึ่งตัวเขียนและเมื่อหนึ่งในนั้นปิดการเชื่อมต่อ หากคุณกำลังใช้ไพพ์ที่มีชื่อคุณสามารถสร้างการเชื่อมต่อได้หลายแบบ (เป็นอนุกรม) แต่แต่ละรายการจะแทนไพพ์ใหม่ในแง่นี้ ดังนั้น "ไปป์" กับเธรดหรือกระบวนการมีความหมายเหมือนกันกับ file descriptor

จากman 7 pipe:

หากตัวให้คำอธิบายไฟล์ทั้งหมดที่อ้างอิงถึงจุดสิ้นสุดการอ่านของไพพ์นั้นถูกปิดการเขียน (2) จะทำให้สัญญาณ SIGPIPE ถูกสร้างขึ้นสำหรับกระบวนการเรียก หากกระบวนการเรียกใช้ละเว้นสัญญาณนี้ดังนั้นการเขียน (2) จะล้มเหลวด้วยข้อผิดพลาด EPIPE

ดังนั้น "ท่อแตก" คือการเขียนสิ่งที่ EOF คือผู้อ่าน


0

ไปป์ที่ขาดเกิดขึ้นเมื่อกระบวนการอ่านจบก่อนกระบวนการเขียน ดังนั้นฉันจะไปกับ (6)


2
อาจมีหลายกระบวนการในการอ่านหรือเขียนไปยังไพพ์และกระบวนการเดียวกันนั้นสามารถอ่านและเขียนได้ นอกจากนี้มันไม่เกี่ยวกับการออกมันเกี่ยวกับการปิดตัวอธิบายไฟล์
Stéphane Chazelas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.