ทำความเข้าใจกับคำสั่ง piped ใน Unix / Linux


16

ฉันมีสองโปรแกรมง่ายๆและ A จะเรียกใช้ก่อนจากนั้นรับ "stdout" ของและใช้เป็น "stdin" สมมติว่าฉันใช้ระบบปฏิบัติการ GNU / Linux และวิธีที่ง่ายที่สุดที่จะทำได้คือ:BABA

./A | ./B

ถ้าฉันต้องอธิบายคำสั่งนี้ฉันจะบอกว่ามันเป็นคำสั่งที่รับอินพุต (เช่นอ่าน) จากผู้ผลิต ( A) และเขียนไปยังผู้บริโภค ( B) นั่นเป็นคำอธิบายที่ถูกต้องหรือไม่? ฉันไม่มีอะไรเลยหรือ



มันไม่ได้เป็นคำสั่งมันเป็นวัตถุ kenerl ที่สร้างขึ้นโดยกระบวนการทุบตีซึ่งใช้เป็น stdout ของกระบวนการ A และ stdin เป็น B กระบวนการสองกระบวนการเริ่มต้นเกือบในเวลาเดียวกัน
炸鱼薯条德里克

1
@ 炸鱼คุณถูกต้อง - สำหรับเคอร์เนลไปป์เป็นวัตถุในระบบไฟล์ pipefs แต่ตราบใดที่เชลล์ตัวเองกังวล - ในทางเทคนิคนั่นคือคำสั่งไปป์ไลน์
Sergiy Kolodyazhnyy

คำตอบ:


26

สิ่งเดียวที่เกี่ยวกับคำถามของคุณที่โดดเด่น ผิดคือคุณพูด

A จะทำงานก่อนจากนั้น B จะได้ stdout ของ A

ในความเป็นจริงทั้งสองโปรแกรมจะเริ่มในเวลาเดียวกัน หากไม่มีอินพุตสำหรับBเมื่อพยายามอ่านข้อมูลจะถูกปิดกั้นจนกว่าจะมีการป้อนข้อมูลให้อ่าน ในทำนองเดียวกันหากไม่มีใครอ่านเอาต์พุตจากAการเขียนของมันจะบล็อกจนกว่าจะมีการอ่านเอาต์พุต (บางส่วนจะถูกบัฟเฟอร์โดยไพพ์)

สิ่งเดียวที่ซิงโครไนซ์กระบวนการที่มีส่วนร่วมในไพพ์ไลน์คือ I / O คือการอ่านและการเขียนข้ามไพพ์ หากไม่มีการเขียนหรือการอ่านเกิดขึ้นกระบวนการทั้งสองจะทำงานโดยอิสระจากกัน หากผู้ใดเพิกเฉยต่อการอ่านหรือการเขียนของอีกฝ่ายกระบวนการที่ถูกเพิกเฉยจะบล็อกและในที่สุดก็ถูกสังหารโดยSIGPIPEสัญญาณ (ถ้าการเขียน) หรือรับเงื่อนไขสิ้นสุดไฟล์ในกระแสอินพุตมาตรฐาน (ถ้าอ่าน) เมื่อกระบวนการอื่นสิ้นสุดลง .

วิธีการอธิบายที่ใช้สำนวนA | Bคือมันเป็นขั้นตอนที่มีสองโปรแกรม เอาต์พุตที่สร้างจากเอาต์พุตมาตรฐานจากโปรแกรมแรกพร้อมที่จะอ่านบนอินพุตมาตรฐานโดยที่สอง ("[เอาต์พุตของ] Aถูกไพพ์ลงใน [อินพุตของ] B") เชลล์ทำหน้าที่วางท่อประปาเพื่อให้สิ่งนี้เกิดขึ้น

หากคุณต้องการใช้คำว่า "consumer" และ "โปรดิวเซอร์" ฉันก็ถือว่าใช้ได้เช่นกัน

ความจริงที่ว่าเหล่านี้เป็นโปรแกรมที่เขียนใน C ไม่เกี่ยวข้อง ความจริงที่ว่านี่คือ Linux, MacOS, OpenBSD หรือ AIX ไม่เกี่ยวข้อง


2
การเขียนไปยังไฟล์ชั่วคราวนั้นถูกใช้ใน DOS เนื่องจากไม่รองรับหลายกระบวนการ
CSM

2
@AlexVong โปรดทราบว่าตัวอย่างของคุณที่มีไฟล์ชั่วคราวจะไม่เทียบเท่า โปรแกรมอาจเลือกที่จะค้นหาแม้ว่าเนื้อหาของไฟล์ แต่ข้อมูลที่หลุดออกจากไพพ์ไม่สามารถค้นหาได้ การสอบที่ดีกว่าคือการใช้mkfifoเพื่อสร้างไพพ์ที่มีชื่อจากนั้นเริ่มต้น B ในการอ่านแบ็คกราวน์จากไพพ์และจากนั้น A ก็เขียนลงไป นี่คือการหยิบยกแม้ว่าเป็นผลจะเหมือนกัน
Kusalananda

2
@AlexVong ความเรียบง่ายที่เกิดขึ้นในบทความนั้นได้หย่าจากท่อจริง การประมวลผลแบบขนานนั้นมีความหมายอย่างแท้จริงไม่ใช่การเพิ่มประสิทธิภาพ มันเป็นคำอธิบายที่สมเหตุสมผลสำหรับเด็กเกี่ยวกับการประเมินผลแบบ monadicหรือการจัดองค์ประกอบสำหรับคนที่เคยเห็นท่อเปลือกหอย แต่ก็ไม่ถูกต้องในทิศทางอื่น เวอร์ชันห้าของ Kusalananda อยู่ใกล้กว่า แต่ส่วนการเผยแพร่ข้อผิดพลาดของโมเดลมีความสำคัญอย่างแท้จริงและไม่สามารถจำลองได้ (ทั้งหมดที่ฉันพูดในฐานะคนที่อยู่บนรถไฟ "เปลือกท่อเป็นเพียงองค์ประกอบของฟังก์ชั่น")
Michael Homer

6
@AlexVong ไม่มีที่สมบูรณ์ออกติดตาม นั่นไม่สามารถอธิบายแม้แต่สิ่งที่เรียบง่ายอย่างเช่น yes | sed 10q
ลุงบิลลี่

1
@ UncleBilly ฉันเห็นด้วยกับตัวอย่างของคุณ นี่แสดงให้เห็นว่าไมเคิลต้องการการดำเนินการแบบขนานจริงๆ มิฉะนั้นเราจะไม่ยกเลิก
อเล็กซ์ Vong

2

คำที่มักใช้ในเอกสารประกอบคือ "ไปป์ไลน์" ซึ่งประกอบด้วยคำสั่งอย่างน้อยหนึ่งคำสั่งให้ดูคำนิยาม POSIX ดังนั้นในทางเทคนิคแล้วการพูดนั้นคือสองคำสั่งที่คุณมีอยู่นั่นคือสองกระบวนการย่อยสำหรับเชลล์fork()+exec() 'ed คำสั่งภายนอกหรือ subshells)

ในส่วนของผู้ผลิตและผู้บริโภคท่อสามารถอธิบายได้ด้วยรูปแบบนั้นเนื่องจาก:

  • โปรดิวเซอร์และผู้บริโภคแชร์บัฟเฟอร์ขนาดคงที่และอย่างน้อยบน Linux และ MacOS X จะมีขนาดคงที่สำหรับบัฟเฟอร์ท่อ
  • ผู้ผลิตและผู้บริโภคมีการเชื่อมโยงอย่างหลวม ๆ คำสั่งในไปป์ไลน์ไม่รู้จักการมีอยู่ของกันและกัน (เว้นแต่ว่าพวกเขากำลังตรวจสอบอยู่ /proc/<pid>/fdไดเรกทอรีอยู่)
  • เขียนถึงผู้ผลิตstdoutและผู้บริโภคอ่านstdinราวกับว่าพวกเขาคำสั่งเดียวถูกประหารชีวิตอาคาที่พวกเขาสามารถอยู่โดยไม่มีกันและกัน

ความแตกต่างที่ฉันเห็นที่นี่คือไม่เหมือนกับ Producer-Consumer ใน languges อื่น ๆ คำสั่งเชลล์ใช้การบัฟเฟอร์และพวกเขาเขียน stdout เมื่อบัฟเฟอร์เต็ม แต่ไม่มีการเอ่ยถึงว่า Producer-Consumer ต้องปฏิบัติตามกฎนั้น - รอเฉพาะเมื่อคิวเต็มหรือทิ้ง ข้อมูล (ซึ่งเป็นอย่างอื่นที่ท่อไม่ได้ทำ)

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