dup2 / dup - ทำไมฉันต้องทำซ้ำ file descriptor?


85

ฉันพยายามทำความเข้าใจการใช้dup2และdup.

จากหน้าคน:

เหตุใดฉันจึงต้องการการโทรจากระบบนั้น การทำซ้ำ file descriptor คืออะไร?

หากฉันมีตัวอธิบายไฟล์เหตุใดฉันจึงต้องการทำสำเนา

ฉันจะขอบคุณถ้าคุณสามารถอธิบายและให้ตัวอย่างที่dup2/ dupจำเป็น

ขอบคุณ


คุณจะใช้ฟังก์ชันการวางท่อของเชลล์โดยไม่มีdupหรือdup2อย่างไร? คุณต้องโทรpipe(2)จากนั้นจึงจะมีตัวอธิบายไฟล์ตัวใดตัวหนึ่งdupเช่นSTDIN_FILENO
Basile Starynkevitch

1
ตัวอย่างที่เป็นไปได้ในทางปฏิบัติใช้ dup หรือ dup2
DrTyrsa

คำตอบ:


48

การเรียกใช้ระบบ dup ซ้ำตัวอธิบายไฟล์ที่มีอยู่โดยส่งคืนไฟล์ใหม่ที่อ้างถึงอ็อบเจ็กต์ I / O ที่อยู่ภายใต้เดียวกัน

Dup อนุญาตให้เชลล์ใช้คำสั่งเช่นนี้:

2> & 1 บอกเชลล์เพื่อให้คำสั่งเป็น file descriptor 2 ซึ่งซ้ำกับ descriptor 1 (เช่น stderr & stdout point เป็น fd เดียวกัน)
ตอนนี้ข้อความแสดงข้อผิดพลาดสำหรับการเรียกlsบนไฟล์ที่ไม่มีอยู่และเอาต์พุตที่ถูกต้องของlsบนไฟล์ที่มีอยู่จะปรากฏในไฟล์tmp1

โค้ดตัวอย่างต่อไปนี้รันโปรแกรม wc โดยมีอินพุตมาตรฐานเชื่อมต่อกับส่วนท้ายของไพพ์

เด็กจับคู่จุดสิ้นสุดการอ่านไปยัง file descriptor 0 ปิดไฟล์ de scriptors ใน p และ execs wc เมื่อ wc อ่านจากอินพุตมาตรฐานมันจะอ่านจากท่อ
นี่คือวิธีการใช้งานท่อโดยใช้ dup ซึ่งตอนนี้คุณใช้ท่อเพื่อสร้างอย่างอื่นนั่นคือความสวยงามของการเรียกระบบคุณสร้างสิ่งหนึ่งขึ้นมาโดยใช้เครื่องมือที่มีอยู่แล้วเครื่องมือเหล่านี้ถูกสร้างขึ้นโดยใช้ อย่างอื่นเป็นต้น .. ในตอนท้ายของการเรียกใช้ระบบเป็นเครื่องมือพื้นฐานที่สุดที่คุณจะได้รับในเคอร์เนล

ไชโย :)


1
ดังนั้นdupจะเป็นประโยชน์สำหรับผู้โทรและไม่lsโปรแกรมตัวเอง? มีประโยชน์อะไรบ้างที่dupใช้ในโปรแกรมเช่น ls เองหากมีการเข้าถึงไฟล์อยู่แล้ว? นี่คือตัวอย่างเช่นlsเขียนข้อผิดพลาด2ซึ่งจะเป็น hardcoded lsดังนั้นฉันมีวิธีการที่จะเอาชนะมันเป็นผู้บริโภคของ ฉันคิดว่านั่นเป็นจุดที่บอบบางไม่ใช่เหรอ?
Nishant

3
โปรแกรมตัวอย่างของคุณดูเหมือนจะมีบั๊ก คุณกำลังโทรหาdup(p[STDIN])แต่ก็ทิ้งผลลัพธ์ไป คุณหมายถึงใช้dup2(p[STDIN], 0)?
Quuxplusone

1
@Quuxplusone dupส่งคืน "ตัวบอกหมายเลขต่ำสุดที่กระบวนการนี้ไม่ได้ใช้งาน" เนื่องจาก fd 0 เพิ่งปิดไปdupควรคืนค่า 0 dup2เป็นเรื่องที่ชัดเจนว่าควรใช้ fd ใดแทนที่จะใช้ fd อิสระต่ำสุดดังนั้นฉันจึงต้องการอย่างนั้น
Wodin

@Wodin: อาฉันพนันได้เลยว่าคุณคิดถูกแล้วว่า OP กำลังคิดอะไรอยู่ ฉันพูดถูกด้วยหรือเปล่าว่า "เพิ่งปิด" เป็นญาติกันและโค้ดของ OP อาจพังต่อหน้าตัวอย่างเช่นเธรดพร้อมกันที่อาจเปิดไฟล์ด้วย
Quuxplusone

@Quuxplusone ฉันสงสัยว่าคุณพูดถูก แต่ไม่รู้แน่ชัด แต่ในกรณีนี้คุณจะมีปัญหาอื่น ๆ หากคุณปิด stdin เพราะคุณต้องการอ่านจากที่อื่นแล้วเธรดอื่นเปิดไฟล์ก่อนที่คุณจะทำมันจะได้รับ fd 0 ถ้าคุณใช้ dup2 มันจะปิด fd ที่เธรดอื่นเปิดดังนั้นเธรดอื่น ตอนนี้จะอ่านจาก (และเขียนถึง?) ไฟล์ที่คุณเปิด อย่างไรก็ตามถ้าจำไม่ผิดคุณไม่ควรโทรexec*จากกระบวนการมัลติเธรด แต่ฉันไม่ใช่ผู้เชี่ยวชาญด้านเธรด :)
Wodin

18

อีกเหตุผลหนึ่งในการทำซ้ำ file descriptor คือใช้กับfdopenไฟล์. fcloseปิดตัวอธิบายไฟล์ที่ถูกส่งผ่านไปfdopenดังนั้นหากคุณไม่ต้องการให้ตัวอธิบายไฟล์ต้นฉบับถูกปิดคุณต้องทำซ้ำด้วยdupก่อน


fdopen()ดูเหมือนว่าจะไม่ซ้ำตัวอธิบายไฟล์เพียงแค่สร้างบัฟเฟอร์ในพื้นที่ผู้ใช้
user218867

3
คุณอ่านคำตอบของฉันผิด ประเด็นคือคุณอาจต้องการdupfd ก่อนที่จะส่งต่อไปยังfdopenตั้งแต่fcloseจะปิด
R .. GitHub STOP HELPING ICE

1
@ theferrit32: หากคุณจัดสรรแฮนเดิลFILEเพื่อเข้าถึงไฟล์ที่เปิดอยู่ก่อนหน้านี้ผ่านอินเทอร์เฟซ stdio คุณต้องเรียกใช้fcloseเพื่อยกเลิกการจัดสรรFILEหมายเลขอ้างอิงนั้น หากคุณต้องการใช้ไฟล์ที่เปิดอยู่ต่อไปหรือหากสถาปัตยกรรมซอฟต์แวร์ของคุณเป็นเช่นนั้นรหัส "เจ้าของ" ดั้งเดิมสำหรับตัวอธิบายไฟล์จะcloseเป็นเช่นนั้นความจริงที่ว่าfcloseยังปิดตัวอธิบายไฟล์ต้นแบบที่คุณส่งให้fdopenก็เป็นปัญหา คุณสามารถหลีกเลี่ยงปัญหานี้ได้โดยใช้dupเพื่อสร้าง file descriptor ใหม่เพื่อให้ไฟล์ที่เปิดอยู่เดียวกันส่งผ่านไปfdopenเพื่อfcloseไม่ให้ปิดไฟล์ต้นฉบับ
R .. GitHub STOP HELPING ICE

1
ประเด็นก็คือว่า fdopen () ย้ายกรรมสิทธิ์ของ FD ไปFILEมากกว่าการคัดลอกมัน นั่นเป็นสิ่งที่ผู้ใช้ควรทราบ ผู้บริโภคที่ต้องการรักษาแฮนเดิลที่ใช้งานได้fdนอกเหนือจากFILEอ็อบเจ็กต์จะต้องทำซ้ำไฟล์fd. นั่นคือทั้งหมด
Conrad Meyer

1
@ConradMeyer: ใช่นั่นเป็นวิธีที่ดีมากในการวางไว้โดยมีข้อสังเกตว่าไม่มีการดำเนินการใด ๆ ที่จะ "ย้ายความเป็นเจ้าของ" ออกไปจากเดิมFILEเมื่อคุณย้ายการเป็นเจ้าของไป
R .. GitHub STOP HELPING ICE

4

dup ใช้เพื่อให้สามารถเปลี่ยนทิศทางผลลัพธ์จากกระบวนการ

ตัวอย่างเช่นหากคุณต้องการบันทึกผลลัพธ์จากกระบวนการคุณทำซ้ำผลลัพธ์ (fd = 1) คุณเปลี่ยนเส้นทาง fd ที่ซ้ำกันไปยังไฟล์จากนั้นแยกและดำเนินการตามกระบวนการและเมื่อกระบวนการเสร็จสิ้นคุณจะเปลี่ยนเส้นทางอีกครั้ง บันทึก fd ลงในเอาต์พุต


4

บางจุดที่เกี่ยวข้องกับ dup / dup2 สามารถสังเกตได้

dup / dup2 - ในทางเทคนิคจุดประสงค์คือการแบ่งปันรายการตารางไฟล์หนึ่งรายการภายในกระบวนการเดียวโดยจัดการที่แตกต่างกัน (หากเรากำลังบังคับให้ descriptor ซ้ำกันโดยค่าเริ่มต้นในกระบวนการย่อยและรายการตารางไฟล์จะถูกแชร์ด้วย)

นั่นหมายความว่าเราสามารถมีตัวอธิบายไฟล์มากกว่าหนึ่งไฟล์ที่มีคุณสมบัติที่แตกต่างกันสำหรับรายการตารางไฟล์เดียวที่เปิดโดยใช้ฟังก์ชัน dup / dup2

(แม้ว่าปัจจุบันจะมีเพียงแฟล็ก FD_CLOEXEC เท่านั้นที่เป็นแอตทริบิวต์เดียวสำหรับ file descriptor)

http://www.gnu.org/software/libc/manual/html_node/Descriptor-Flags.html

ความแตกต่างคือ (สำหรับข้อสุดท้าย) - นอกเหนือจากค่า errno บางค่า beteen dup2 และ fcntl close ตามด้วย fcntl อาจเพิ่มเงื่อนไขการแข่งขันเนื่องจากมีการเรียกใช้ฟังก์ชันสองฟังก์ชัน

สามารถตรวจสอบรายละเอียดได้จาก http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html

ตัวอย่างการใช้งาน -

ตัวอย่างหนึ่งที่น่าสนใจในขณะที่ใช้ job control ในเชลล์ซึ่งสามารถดูการใช้ dup / dup2 ได้ในลิงค์ด้านล่าง

http://www.gnu.org/software/libc/manual/html_node/Launching-Jobs.html#Launching-Jobs

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