ไพพ์เป็นไฟล์ที่เปิดในระบบไฟล์ในเคอร์เนลและไม่สามารถเข้าถึงได้เหมือนไฟล์ปกติบนดิสก์ มันจะถูกบัฟเฟอร์โดยอัตโนมัติเฉพาะกับขนาดที่กำหนดและในที่สุดจะปิดกั้นเมื่อเต็ม ซึ่งแตกต่างจากไฟล์ที่มาจากอุปกรณ์บล็อกท่อมีพฤติกรรมเหมือนอุปกรณ์ตัวอักษรดังนั้นโดยทั่วไปแล้วไม่รองรับlseek()
และข้อมูลที่อ่านจากพวกมันจะไม่สามารถอ่านได้อีกเหมือนที่คุณทำกับไฟล์ปกติ
สตริงที่นี่เป็นไฟล์ปกติที่สร้างขึ้นในระบบไฟล์ที่เมาท์ เชลล์สร้างไฟล์และเก็บ descriptor ไว้ในขณะที่ลบลิงค์ระบบไฟล์ออกทันที(และทำการลบ)ก่อนที่มันจะเขียน / อ่านไบต์ไปยัง / จากไฟล์ เคอร์เนลจะรักษาพื้นที่ที่จำเป็นสำหรับไฟล์ไว้จนกว่ากระบวนการทั้งหมดจะปล่อยตัวอธิบายทั้งหมด หากเด็กที่อ่านจาก descriptor ดังกล่าวมีความสามารถในการทำเช่นนั้นก็สามารถ rewound ด้วยlseek()
และอ่านอีกครั้ง
ในทั้งสองกรณีโทเค็น<<<
และ|
เป็นตัวแทนของ file-descriptors และไม่จำเป็นต้องใช้ไฟล์เอง คุณสามารถรับความคิดที่ดีขึ้นของสิ่งที่เกิดขึ้นโดยทำสิ่งที่ชอบ:
readlink /dev/fd/1 | cat
...หรือ...
ls -l <<<'' /dev/fd/*
ความแตกต่างที่สำคัญที่สุดระหว่างสองไฟล์คือ here-string / doc นั้นค่อนข้างเป็นเรื่องที่เกิดขึ้นครั้งเดียว - เชลล์เขียนข้อมูลทั้งหมดลงไปก่อนที่จะเสนอ descriptor การอ่านให้กับเด็ก ในอีกทางหนึ่งเชลล์จะเปิดไพพ์บน descriptor ที่เหมาะสมและห้ามให้เด็กจัดการกับไพพ์นั้น - ดังนั้นจึงถูกเขียน / อ่านพร้อมกันที่ปลายทั้งสอง
อย่างไรก็ตามความแตกต่างเหล่านี้เป็นจริงโดยทั่วไปเท่านั้น เท่าที่ผมทราบ(ซึ่งไม่ได้จริงๆสิ่งที่ไกล)นี่คือความจริงของสวยมากเปลือกซึ่งจัดการทุก<<<
ที่นี่สตริงสั้นมือสำหรับการเปลี่ยนเส้นทางที่นี่เอกสารมีข้อยกเว้นเดียวของ<<
, , และอื่น ๆ ที่สายพันธุ์ที่มีแนวโน้มที่จะกลับมาที่นี่-เอกสารที่มีท่อแม้ว่าและดังนั้นในเปลือกหอยเหล่านั้นมีจริงๆคือความแตกต่างน้อยมากระหว่างสองหลังจากทั้งหมดyash
yash
busybox
dash
ash
ตกลง - สองข้อยกเว้น ตอนนี้ฉันกำลังคิดเกี่ยวกับมัน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 ของเชลล์พาเรนต์$$
เมื่อขยาย แม้ว่าbash
subshells เป็นกระบวนการที่แยกจากกันแน่นอนแต่$$
พารามิเตอร์เชลล์พิเศษไม่ใช่แหล่งข้อมูลที่เชื่อถือได้ของข้อมูลนี้ ยังเด็ก subshell ของเปลือกไม่ได้ปฏิเสธที่จะรายงานได้อย่างถูกต้องของมันsh
$PPID