เหตุใดจึงใช้ไพพ์ที่มีชื่อแทนที่จะเป็นไฟล์


42

ฉันเพิ่งอ่านเกี่ยวกับชื่อไปป์และฉันไม่เข้าใจว่าทำไมมันถึงมีอยู่
ฉันได้อ่านบางที่ว่าการใช้ไพพ์ที่มีชื่อนั้นใช้เวลาน้อยกว่าการใช้ไฟล์

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

ดังนั้นข้อดีอยู่ที่ไหน?


นี่ไม่ใช่ส่วนหนึ่งของการมอบหมายในชั้นเรียนใช่มั้ย
don.joey

6
ไม่ ... จริงๆแล้วฉันกำลังดูบันทึกการบรรยายเมื่อฉันพบคำถามนี้และฉันไม่สามารถตอบได้ ... และถ้ามันเป็นงานที่มอบหมายฉันไม่เห็นว่ามันจะเกี่ยวข้องกัน ... มันไม่เหมือนกัน ฉันจะไม่ค้นหาคำตอบจนกว่าฉันจะพบมัน
user3122885

คำตอบ:


41

เกือบทุกอย่างใน Linux ถือได้ว่าเป็นไฟล์แต่ความแตกต่างหลักระหว่างไฟล์ปกติกับไพพ์ที่มีชื่อคือไพพ์ที่มีชื่อนั้นเป็นอินสแตนซ์พิเศษของไฟล์ที่ไม่มีเนื้อหาในระบบไฟล์

นี่คือคำพูดจากman fifo:

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

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

จริง ๆ แล้วไพพ์ที่มีชื่อจะไม่ทำอะไรเลยจนกว่ากระบวนการบางอย่างจะอ่านและเขียนลงไป ไม่ใช้พื้นที่บนฮาร์ดดิสก์ (ยกเว้นข้อมูลเมตาเล็กน้อย) ไม่ใช้ CPU

คุณสามารถตรวจสอบได้โดยทำสิ่งนี้:

สร้างไปป์ที่มีชื่อ

$ mkfifo /tmp/testpipe

ไปที่ไดเรกทอรีบางตัว/home/user/Documentsและ gzip ทุกอย่างที่อยู่ในนั้นโดยใช้ไพพ์ที่มีชื่อ

$ cd /home/user/Documents
$ tar cvf - . | gzip > /tmp/testpipe &
[1] 28584

ที่นี่คุณควรเห็น PID ของกระบวนการ gzip ในตัวอย่างของเรามันคือ 28584

ตรวจสอบสิ่งที่ PID กำลังทำอยู่

$ ps u -P 28584
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
c0rp     28584  0.0  0.0  29276  7800 pts/8    S    00:08   0:00 bash

คุณจะเห็นว่ามันคือการใช้ทรัพยากร การใช้งาน CPU 0%, การใช้งานหน่วยความจำ 0%

ตรวจสอบลางสังหรณ์เกี่ยวกับการใช้พื้นที่ไฟล์

$ du -h /tmp/testpipe
0   testpipe

และ0ไม่มีอะไรอีกแล้ว สามารถใช้ testpipe อีกครั้งหากจำเป็น

อย่าลืมที่จะฆ่า gzip kill -15 28584ใช้ และลบไปป์ที่มีชื่อของเราโดยใช้rm /tmp/testpipe

ตัวอย่างประเพณี

คุณสามารถเปลี่ยนเส้นทางเกือบทุกอย่างโดยใช้ชื่อไปป์ ตัวอย่างเช่นคุณสามารถเห็นพร็อกซีหนึ่งบรรทัดนี้

นอกจากนี้ที่นี่เป็นอีกหนึ่งคำอธิบายที่ดีของการใช้ไปป์ที่มีชื่อ คุณสามารถกำหนดค่าสองกระบวนการในเซิร์ฟเวอร์เดียวเพื่อสื่อสารโดยใช้ไพพ์ที่มีชื่อแทนที่จะเป็น TCP / IP สแต็ก มันเร็วกว่ามากและไม่โหลดทรัพยากรเครือข่าย ตัวอย่างเช่นเว็บเซิร์ฟเวอร์ของคุณสามารถสื่อสารกับฐานข้อมูลโดยตรงโดยใช้ไพพ์ที่มีชื่อแทนที่จะใช้ที่localhostอยู่หรือฟังพอร์ตบางตัว


14

มันเป็นความจริงที่คุณจะไม่ใช้หน่วยความจำระบบ แต่ความจริงที่คุณไม่ได้ใช้ cpu ในตัวอย่างของคุณเป็นเพียงเพราะคุณไม่ได้อ่านไปป์ดังนั้นกระบวนการกำลังรอ

ลองพิจารณาตัวอย่างต่อไปนี้:

mkfifo /tmp/testpipe
tar cvf - / | gzip > /tmp/testpipe

ตอนนี้เปิดคอนโซลใหม่และเรียกใช้:

watch -n 1 'ps u -P $(pidof tar)

และในคอนโซลที่สาม:

cat /tmp/testpipe > /dev/null

ถ้าคุณดูนาฬิกา cmd (ภาคเรียนที่ 2) มันจะแสดงการใช้ซีพียูที่เพิ่มขึ้น!


1
คำตอบนี้เกี่ยวกับคำตอบของ
c0rp

2

นี่คือกรณีการใช้งานที่ pipes ที่มีชื่อสามารถช่วยคุณประหยัดเวลาได้มากโดยการลบ I / O

สมมติว่าคุณมี BigFile เช่น 10G

คุณยังได้แยก BigFile นี้เป็นชิ้น ๆ 1G, BigFileSplit_01 ถึง BigFile_Split_10

ตอนนี้คุณมีข้อสงสัยในความถูกต้องของ BigFileSplit_05

อย่างไร้เดียงสาโดยไม่มีชื่อไปป์คุณจะต้องสร้างตัวแยกใหม่จาก BigFile และเปรียบเทียบ:

dd if=BigFile of=BigFileSplitOrig_05 bs=1G skip=4 count=1
diff -s BigFileSplitOrig_05 BigFileSplit_05
rm BigFileSplitOrig_05

ด้วยชื่อท่อที่คุณจะทำ

mkfifo BigFileSplitOrig_05
dd if=BigFile of=BigFileSplitOrig_05 bs=1G skip=4 count=1 &
diff -s BigFileSplitOrig_05 BigFileSplit_05
rm BigFileSplitOrig_05

นั่นอาจไม่ปรากฏให้เห็นตั้งแต่แรกเห็นความแตกต่างใหญ่ ... แต่ในเวลาที่แตกต่างกันมาก!

ตัวเลือกที่ 1:

  • วว: อ่าน 1G / เขียน 1G (1)
  • diff: อ่าน 2G
  • rm: คลัสเตอร์ที่จัดสรรฟรี / ลบรายการไดเร็กทอรี

ตัวเลือก 2:

  • วว: ไม่มีอะไร! (ไปที่ชื่อ pipe)
  • diff: อ่าน 2G
  • rm: ไม่มีคลัสเตอร์ที่จัดสรรให้จัดการ (เราไม่ได้เขียนอะไรลงในระบบไฟล์) / ลบรายการไดเรกทอรี

ดังนั้นโดยทั่วไปไปป์ที่มีชื่อจะช่วยคุณในการอ่านและเขียนของ 1G รวมถึงการทำความสะอาดระบบไฟล์บางส่วน (เนื่องจากเราไม่ได้เขียนอะไรลงในระบบไฟล์

การไม่ทำ I / O โดยเฉพาะเขียนก็เป็นสิ่งที่ดีเช่นกันในการหลีกเลี่ยงการสึกหรอของดิสก์ มันน่าสนใจยิ่งขึ้นเมื่อคุณทำงานกับ SSD เนื่องจากมีจำนวนการเขียน จำกัด ก่อนที่เซลล์จะตาย

(1) เห็นได้ชัดว่ามีอีกตัวเลือกหนึ่งคือสร้างไฟล์ชั่วคราวเป็น RAM ตัวอย่างเช่นหาก / tmp ติดตั้งกับ RAM (tmpfs) อย่างไรก็ตามคุณจะถูก จำกัด ด้วยขนาดของ RAM disk ในขณะที่ "named pipe trick" ไม่มีข้อ จำกัด


0

คุณสามารถปล่อยให้โปรแกรมหยุดนิ่งและฟังไพพ์ที่มีชื่อสำหรับเหตุการณ์ภายนอกบางอย่าง ทันทีที่มีเหตุการณ์ภายนอกเกิดขึ้น (f.ex. การมาถึงของข้อมูลใหม่บางอย่าง) สิ่งนี้สามารถตรวจพบได้โดยโปรแกรมอื่นซึ่งจะเปิดไพพ์สำหรับการเขียนโดยการเขียนข้อมูลเหตุการณ์ที่เกี่ยวข้องไปยังไพพ์ เมื่อออกคำสั่งปิดโปรแกรมการฟังจะรับกระแสข้อมูลผ่านไพพ์ผ่านคำสั่งการอ่านและพร้อมที่จะประมวลผลสิ่งที่ได้รับ อย่าลืมปิดท่อหลังจากอ่านเนื้อหา โปรแกรมฟังสามารถส่งคืนผลลัพธ์ของการประมวลผลผ่านทางเดียวกันหรือผ่านไพพ์ที่มีชื่ออื่น การสื่อสารระหว่างโปรแกรมดังกล่าวสะดวกมากในบางครั้ง

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