การวางท่อไม่จำเป็นต้องให้อินสแตนซ์แรกเสร็จสิ้นก่อนที่อีกอันหนึ่งจะเริ่มทำงาน ที่จริงแล้วสิ่งที่ทำจริงๆคือการเปลี่ยนstdoutของอินสแตนซ์แรกไปยังstdinของอันที่สองดังนั้นพวกเขาจึงสามารถทำงานพร้อมกันได้ (เนื่องจากต้องใช้ fork fork เพื่อทำงาน)
เอาท์พุทของ:
คืออะไร? สิ่งที่ถูกส่งผ่านไปยังอีก:
หรือไม่
':' ไม่ได้เขียนอะไรไปยังอินสแตนซ์อื่น ':' มันแค่เปลี่ยนเส้นทางstdoutไปยังstdinของอินสแตนซ์ที่สอง ถ้ามันเขียนอะไรบางอย่างระหว่างการประหารชีวิต (ซึ่งมันไม่เคยจะทำได้เพราะมันไม่ทำอะไรนอกจากการฟอร์กตัวเอง) มันจะไปที่stdinของอินสแตนซ์อื่น
มันช่วยให้จินตนาการถึงstdinและstdoutเป็นกอง:
สิ่งใดก็ตามที่เขียนไปยังstdinจะถูกซ้อนขึ้นเมื่อโปรแกรมตัดสินใจอ่านจากนั้นในขณะที่stdoutทำงานในลักษณะเดียวกัน: กองที่คุณสามารถเขียนได้ดังนั้นโปรแกรมอื่น ๆ สามารถอ่านได้เมื่อต้องการ
ด้วยวิธีนี้มันง่ายที่จะจินตนาการถึงสถานการณ์เช่นไพพ์ที่ไม่มีการสื่อสารเกิดขึ้น (สองกองว่างเปล่า) หรือการเขียนและอ่านที่ไม่ซิงโครไนซ์
วิธีการที่ถูกดำเนินการสองครั้งว่า? ในความคิดของฉันไม่มีอะไรถูกส่งผ่านไปยังวินาที:
จนกว่าการดำเนินการครั้งแรกจะ:
เสร็จสิ้นซึ่งจริงๆแล้วจะไม่มีวันสิ้นสุด
เนื่องจากเราเพิ่งจะเปลี่ยนทิศทางอินพุทและเอาท์พุทของอินสแตนซ์ดังนั้นจึงไม่มีข้อกำหนดสำหรับอินสแตนซ์แรกที่จะเสร็จสิ้นก่อนที่อินสแตนซ์ที่สองจะเริ่มต้นขึ้น โดยปกติแล้วมันต้องการให้ทั้งสองทำงานพร้อมกันเพื่อที่สองสามารถทำงานกับข้อมูลที่ถูกแยกวิเคราะห์โดยอันแรกได้ทันที นั่นคือสิ่งที่เกิดขึ้นที่นี่ทั้งคู่จะถูกเรียกโดยไม่ต้องรอให้เสร็จก่อน ที่ใช้กับบรรทัดคำสั่งของchain chainsทั้งหมด
ฉันคิดว่าตรรกะเดียวกันนี้ใช้ได้กับ: () {: |: &} ;: และ
:(){ : & };:
ทำงานเช่นเดียวกับ
:(){ :|: & };:
ตัวแรกไม่ทำงานเพราะถึงแม้ว่ามันจะเรียกใช้ซ้ำตัวเองฟังก์ชันจะถูกเรียกในพื้นหลัง ( : &
) คนแรก:
ไม่รอจนกว่า "เด็ก" :
จะกลับมาก่อนที่จะจบตัวเองดังนั้นในที่สุดคุณอาจมีเพียงหนึ่งตัวอย่างของการ:
ทำงาน หากคุณมี:(){ : };:
มันจะทำงานแม้ว่าตั้งแต่แรก:
จะรอให้ "ลูก" :
กลับมาซึ่งจะรอ "ลูก" ของตัวเอง:
เพื่อกลับไปและอื่น ๆ
ต่อไปนี้เป็นคำสั่งต่าง ๆ ที่มีลักษณะเป็นจำนวนอินสแตนซ์ที่กำลังทำงาน:
:(){ : & };:
1 อินสแตนซ์ (การโทร:
และการออก) -> 1 อินสแตนซ์ (การโทร:
และการออก) -> 1 อินสแตนซ์ (การโทร:
และการปิด) -> 1 อินสแตนซ์ -> ...
:(){ :|: &};:
1 อินสแตนซ์ (เรียก 2 :
และออกจาก) -> 2 อินสแตนซ์ (แต่ละคนโทร 2 :
และออกจาก) -> 4 อินสแตนซ์ (แต่ละคนเรียก 2 :
และออกจาก) -> 8 อินสแตนซ์ -> ...
:(){ : };:
1 อินสแตนซ์ (เรียก:
และรอให้มันส่งคืน) -> 2 อินสแตนซ์ (เด็กโทรอีกครั้ง:
และรอให้ส่งคืน) -> 3 อินสแตนซ์ (เด็กโทรอีกครั้ง:
และรอให้มันส่งคืน) -> 4 อินสแตนซ์ -> ...
:(){ :|: };:
1 อินสแตนซ์ (โทร 2 :
และรอให้พวกเขากลับมา) -> 3 อินสแตนซ์ (เด็ก ๆ โทรหา 2 :
คนและรอให้พวกเขากลับมา) -> 7 อินสแตนซ์ (เด็กโทรหา 2 :
คนแต่ละคนและรอให้พวกเขากลับมา) -> 15 ครั้ง -> ...
อย่างที่คุณเห็นการเรียกใช้ฟังก์ชั่นในพื้นหลัง (โดยใช้&
) ช้าลงในการวางระเบิดเนื่องจากผู้เรียกจะออกจากกันก่อนที่ฟังก์ชันที่เรียกใช้จะกลับมา
:|:
ที่สอง:
ไม่จำเป็นต้องรอคำสั่งแรกเสร็จสมบูรณ์