ไพพ์เป็นไฟล์ที่เปิดในระบบไฟล์ในเคอร์เนลและไม่สามารถเข้าถึงได้เหมือนไฟล์ปกติบนดิสก์ มันจะถูกบัฟเฟอร์โดยอัตโนมัติเฉพาะกับขนาดที่กำหนดและในที่สุดจะปิดกั้นเมื่อเต็ม ซึ่งแตกต่างจากไฟล์ที่มาจากอุปกรณ์บล็อกท่อมีพฤติกรรมเหมือนอุปกรณ์ตัวอักษรดังนั้นโดยทั่วไปแล้วไม่รองรับlseek()และข้อมูลที่อ่านจากพวกมันจะไม่สามารถอ่านได้อีกเหมือนที่คุณทำกับไฟล์ปกติ
สตริงที่นี่เป็นไฟล์ปกติที่สร้างขึ้นในระบบไฟล์ที่เมาท์ เชลล์สร้างไฟล์และเก็บ descriptor ไว้ในขณะที่ลบลิงค์ระบบไฟล์ออกทันที(และทำการลบ)ก่อนที่มันจะเขียน / อ่านไบต์ไปยัง / จากไฟล์ เคอร์เนลจะรักษาพื้นที่ที่จำเป็นสำหรับไฟล์ไว้จนกว่ากระบวนการทั้งหมดจะปล่อยตัวอธิบายทั้งหมด หากเด็กที่อ่านจาก descriptor ดังกล่าวมีความสามารถในการทำเช่นนั้นก็สามารถ rewound ด้วยlseek()และอ่านอีกครั้ง
ในทั้งสองกรณีโทเค็น<<<และ|เป็นตัวแทนของ file-descriptors และไม่จำเป็นต้องใช้ไฟล์เอง คุณสามารถรับความคิดที่ดีขึ้นของสิ่งที่เกิดขึ้นโดยทำสิ่งที่ชอบ:
readlink /dev/fd/1 | cat
...หรือ...
ls -l <<<'' /dev/fd/*
ความแตกต่างที่สำคัญที่สุดระหว่างสองไฟล์คือ here-string / doc นั้นค่อนข้างเป็นเรื่องที่เกิดขึ้นครั้งเดียว - เชลล์เขียนข้อมูลทั้งหมดลงไปก่อนที่จะเสนอ descriptor การอ่านให้กับเด็ก ในอีกทางหนึ่งเชลล์จะเปิดไพพ์บน descriptor ที่เหมาะสมและห้ามให้เด็กจัดการกับไพพ์นั้น - ดังนั้นจึงถูกเขียน / อ่านพร้อมกันที่ปลายทั้งสอง
อย่างไรก็ตามความแตกต่างเหล่านี้เป็นจริงโดยทั่วไปเท่านั้น เท่าที่ผมทราบ(ซึ่งไม่ได้จริงๆสิ่งที่ไกล)นี่คือความจริงของสวยมากเปลือกซึ่งจัดการทุก<<<ที่นี่สตริงสั้นมือสำหรับการเปลี่ยนเส้นทางที่นี่เอกสารมีข้อยกเว้นเดียวของ<< , , และอื่น ๆ ที่สายพันธุ์ที่มีแนวโน้มที่จะกลับมาที่นี่-เอกสารที่มีท่อแม้ว่าและดังนั้นในเปลือกหอยเหล่านั้นมีจริงๆคือความแตกต่างน้อยมากระหว่างสองหลังจากทั้งหมดyashyashbusyboxdashash
ตกลง - สองข้อยกเว้น ตอนนี้ฉันกำลังคิดเกี่ยวกับมันksh93ไม่ได้ทำไปป์ไลน์เลย|แต่แทนที่จะจัดการกับซ็อกเก็ตธุรกิจทั้งหมด - แม้ว่ามันจะทำไฟล์ tmp ที่ถูกลบสำหรับ<<<*คนอื่น ๆ ยิ่งไปกว่านั้นมันวางเฉพาะส่วนแยกของไปป์ไลน์ในสภาพแวดล้อม subshellซึ่งเป็นประเภทของ POSIX Euphemism อย่างน้อยก็ทำหน้าที่เหมือน subshellและดังนั้นแม้จะไม่ทำส้อม
ความจริงก็คือผลลัพธ์ของมาตรฐาน @ PSkocik (ซึ่งมีประโยชน์มาก)ที่นี่อาจแตกต่างกันอย่างกว้างขวางด้วยเหตุผลหลายประการและส่วนใหญ่ขึ้นอยู่กับการใช้งาน สำหรับการตั้งค่าเอกสารที่นี่ปัจจัยที่สำคัญที่สุดคือ${TMPDIR}ประเภทของระบบไฟล์เป้าหมายและการกำหนดค่าแคช / ความพร้อมใช้งานในปัจจุบันและยังคงปริมาณข้อมูลที่จะเขียน สำหรับไพพ์จะเป็นขนาดของกระบวนการเชลล์เองเนื่องจากการทำสำเนาจะทำสำหรับส้อมที่ต้องการ ด้วยวิธีนี้bashมันแย่มากที่การตั้งค่าไปป์ไลน์(รวมการแทนที่$(คำสั่ง)) - เพราะมันใหญ่และช้ามากแต่ด้วยความที่ksh93แทบจะไม่แตกต่างกันเลย
นี่เป็นอีกตัวอย่างกระสุนเล็ก ๆ น้อย ๆ ที่แสดงให้เห็นว่าเชลล์แยกย่อย subshells สำหรับไพพ์ไลน์อย่างไร:
pipe_who(){ echo "$$"; sh -c 'echo "$PPID"'; }
pipe_who
pipe_who | { pipe_who | cat /dev/fd/3 -; } 3<&0
32059 #bash's pid
32059 #sh's ppid
32059 #1st subshell's $$
32111 #1st subshell sh's ppid
32059 #2cd subshell's $$
32114 #2cd subshell sh's ppid
ความแตกต่างระหว่างสิ่งที่pipe_who()รายงานการโทรไปป์ไลน์และรายงานของการรันหนึ่งครั้งในเชลล์ปัจจุบันเกิดจากพฤติกรรมที่ระบุ(ของ subshell ใน)การอ้างสิทธิ์ pid ของเชลล์พาเรนต์$$เมื่อขยาย แม้ว่าbashsubshells เป็นกระบวนการที่แยกจากกันแน่นอนแต่$$พารามิเตอร์เชลล์พิเศษไม่ใช่แหล่งข้อมูลที่เชื่อถือได้ของข้อมูลนี้ ยังเด็ก subshell ของเปลือกไม่ได้ปฏิเสธที่จะรายงานได้อย่างถูกต้องของมันsh$PPID