ยูทิลิตี้ Linux นั้นฉลาดเมื่อใช้คำสั่ง piped หรือไม่?


23

ฉันเพิ่งรันคำสั่งสองสามคำสั่งในเทอร์มินัลและฉันเริ่มสงสัยว่า Unix / Linux จะใช้ทางลัดเมื่อเรียกใช้คำสั่ง piped หรือไม่

ตัวอย่างเช่นสมมติว่าฉันมีไฟล์ที่มีหนึ่งล้านเส้นแรก 10 hello worldซึ่งประกอบด้วย หากคุณรันคำสั่งคำสั่งgrep "hello world" file | headแรกจะหยุดทันทีที่พบ 10 บรรทัดหรือไม่หรือค้นหาทั้งไฟล์ก่อนหรือไม่


2
นั่นเป็นเหตุผลที่ gnu grep มี-mเหตุผล
พอลทอมบลิ

3
เครื่องเทอร์มินัลไม่เกี่ยวข้องกับมัน คำสั่ง Piped ได้รับการจัดการโดยเชลล์
Keith Thompson

@ KeithThompson ให้อภัยความไม่รู้ของฉันฉันไม่ใหญ่ในคำศัพท์ไม่แน่ใจว่าจะเรียกมันว่า terminal, shell หรือ command line อย่าลังเลที่จะแนะนำการแก้ไขคำถามของฉัน :)
DisgruntledGoat

คำตอบ:


30

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

หากgrepพบมากกว่า 10 บรรทัดที่ระบุว่า "สวัสดีโลก" headจะมีทั้งหมด 10 บรรทัดที่ต้องการและปิดไปป์ สิ่งนี้จะทำให้grepถูกฆ่าด้วย SIGPIPE ดังนั้นจึงไม่จำเป็นต้องทำการสแกนไฟล์ที่มีขนาดใหญ่มาก


2
ดังนั้นฉันเดาว่าเนื่องจากสภาพการแข่งขัน grep อาจอ่านรูปแบบที่ 11 หรือ 12 แล้ว แต่อาจไม่ใช่ 100,000 หรือไม่
ผู้ใช้ที่ไม่รู้จัก

3
ขึ้นอยู่กับความยาวของบรรทัดและขนาดของ pipe pipe แต่คำตอบสั้น ๆ คือ grep จะอ่านข้อมูลเพิ่มเติมในจำนวนที่ จำกัด ก่อนที่จะถูกฆ่า
dmckee

1
@userunknown แน่นอน
psusi

เยี่ยมฉันไม่ทราบว่าเกิดอะไรขึ้น ฉันคิดว่าgrepจะดำเนินการส่งออกเป็นโมฆะคล้ายกับ/dev/null
Izkata

15

เมื่อโปรแกรมพยายามเขียนลงในไพพ์และไม่มีกระบวนการอ่านจากไพพ์นั้นโปรแกรมตัวเขียนจะรับสัญญาณSIGPIPE การกระทำเริ่มต้นเมื่อโปรแกรมได้รับ SIGPIPE คือการยกเลิกโปรแกรม โปรแกรมสามารถเลือกที่จะไม่สนใจสัญญาณ SIGPIPE ซึ่งในกรณีที่การเขียนส่งคืนข้อผิดพลาด ( EPIPE)

ในตัวอย่างของคุณนี่คือเส้นเวลาของสิ่งที่เกิดขึ้น:

  • grepและheadคำสั่งเริ่มต้นขึ้นในแบบคู่ขนาน
  • grep อ่านอินพุตบางส่วนแล้วเริ่มประมวลผล
  • เมื่อถึงจุดหนึ่งgrepผลิตชิ้นแรกของการส่งออก
  • head อ่านอันแรกและเขียนออกมา
  • สมมติว่ามีเส้นเพียงพอหลังจากการแข่งขัน 10 ครั้งแรก (มิฉะนั้นgrepอาจสิ้นสุดก่อน) ในที่สุดheadจะพิมพ์ออกมาตามจำนวนบรรทัดที่ต้องการ ณ จุดนี้headออก
  • ทั้งนี้ขึ้นอยู่กับความเร็วสัมพัทธ์ของgrepและheadกระบวนการgrepอาจมีการสะสมข้อมูลบางส่วนและไม่พิมพ์ออกยัง ในขณะที่headออกgrepอาจกำลังอ่านอินพุตหรือทำการประมวลผลภายในซึ่งในกรณีนี้มันจะยังคงทำเช่นนั้นต่อไป
  • ในไม่ช้าgrepจะเขียนข้อมูลที่ประมวลผล ณ จุดนั้นมันจะได้รับ SIGPIPE และตาย

เป็นไปได้ว่าgrepจะประมวลผลอินพุตมากกว่าที่จำเป็นเล็กน้อยโดยทั่วไป แต่โดยทั่วไปจะมีเพียงไม่กี่กิโลไบต์:

  • headโดยทั่วไปแล้วจะอ่านเป็นชิ้น ๆ ไม่กี่กิโลไบต์ (เพราะประสิทธิภาพมากกว่าการreadเรียกใช้ระบบสำหรับแต่ละไบต์ - พฤติกรรมนี้เรียกว่าการบัฟเฟอร์) ดังนั้นส่วนที่เหลือของชิ้นสุดท้ายหลังจากที่บรรทัดสุดท้ายที่ต้องการถูกยกเลิก
  • อาจมีข้อมูลบางอย่างในระหว่างการขนส่งเนื่องจากไพพ์มีบัฟเฟอร์ที่เกี่ยวข้องซึ่งจัดการโดยเคอร์เนล (มัก 512 ไบต์) ข้อมูลนี้จะถูกยกเลิก
  • grepอาจสะสมข้อมูลบางส่วนที่พร้อมจะกลายเป็นก้อนข้อมูล (บัฟเฟอร์อีกครั้ง) มันจะได้รับ SIGPIPE เมื่อพยายามลบบัฟเฟอร์ของเอาต์พุต

ทั้งหมดในทุกระบบได้รับการออกแบบอย่างแม่นยำเพื่อให้ระบบกรองทำงานได้อย่างมีประสิทธิภาพ โปรแกรมที่ต้องดำเนินการต่อไปเมื่อช่องสัญญาณขาออกของพวกเขาดับลงจะต้องดำเนินการตามขั้นตอนของการละเว้นสัญญาณ SIGPIPE


3

Sortof, ไปป์ไลน์ใช้งานได้ดังนี้: มันจะประมวลผลคำสั่งแรกก่อนจากนั้นคำสั่งที่สองในกรณีของคุณ

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

หาก B พยายามอ่านจากไปป์ แต่ไม่มีข้อมูลBจะรอจนกว่าข้อมูลจะมาถึง หากBกำลังอ่านจากดิสก์Bอาจมีปัญหาเดียวกันและต้องรอจนกว่าการอ่านดิสก์จะเสร็จสิ้น การเปรียบเทียบที่ใกล้ชิดยิ่งขึ้นจะอ่านจากแป้นพิมพ์ ที่นั่นBจะต้องรอให้ผู้ใช้พิมพ์ แต่ในกรณีเหล่านี้ทั้งหมด B ได้เริ่มดำเนินการ "อ่าน" และต้องรอจนกว่าจะเสร็จสิ้น แต่ถ้าBเป็นคำสั่งที่ต้องการเพียงบางส่วนของเอาต์พุตAหลังจากนั้นเมื่อถึงจุดหนึ่งที่Bระดับการป้อนข้อมูลAของ SIGPIPE

หากAพยายามเขียนไปยังไปป์และไปป์เต็มAต้องรอให้บางห้องในไพพ์ว่าง Aอาจมีปัญหาเดียวกันหากเขียนไปยังเทอร์มินัล เทอร์มินัลมีการควบคุมการไหลและสามารถกลั่นกรองข้อมูลได้ ไม่ว่าในกรณีใดถึงAจะเริ่มต้นการดำเนินการ "เขียน" และจะรอจนกว่าการดำเนินการเขียนจะเสร็จสิ้น

AและBทำตัวเป็นกระบวนการร่วมแม้ว่าไม่ใช่กระบวนการร่วมทั้งหมดจะสื่อสารกับไปป์ ไม่สามารถควบคุมได้อย่างสมบูรณ์


1
คำถามคือ: "จะทำอย่างไรเมื่อ B ปิดด้านข้างของท่อ"
enzotib

2
นั่นจะไม่ใช่ 'ท่อแตก' ใช่ไหม
Patkos Csaba

1
หากโปรแกรมพยายามอ่าน / เขียนจาก / ไปยังไปป์ที่ปิด (เช่นheadออก) สัญญาณ SIGPIPE จะเกิดขึ้นในโปรแกรมและพฤติกรรมเริ่มต้นคือการออก
Lekensteyn

คำถามนี้ตอบคำถามได้อย่างไร? ดูเหมือนว่าคำตอบของ psusiจะสั้นกว่าและตรงประเด็นมากขึ้น
jw013

1

grepไม่มีการควบคุมไปป์โดยตรง (เพิ่งได้รับข้อมูล) และไพพ์ไม่มีการควบคุมโดยตรงgrep(มันเป็นเพียงการส่งข้อมูล) ...

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

เทอร์มินัลค่อนข้างถูกตัดการเชื่อมต่อจากการทำงานภายในของgrepและการshellกระทำของการวางท่อ ... เทอร์มินัลเป็นเพียงแป้นยิงและแสดงผล ...

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