อะไรจะเป็นคำอธิบายที่ง่ายขึ้นของ file descriptors เทียบกับ Wikipedia ทำไมพวกเขาต้องการ? สมมติว่าใช้กระบวนการเชลล์เป็นตัวอย่างและนำไปใช้อย่างไร
ตารางกระบวนการมีตัวอธิบายไฟล์มากกว่าหนึ่งไฟล์หรือไม่ ถ้าใช่ทำไม
อะไรจะเป็นคำอธิบายที่ง่ายขึ้นของ file descriptors เทียบกับ Wikipedia ทำไมพวกเขาต้องการ? สมมติว่าใช้กระบวนการเชลล์เป็นตัวอย่างและนำไปใช้อย่างไร
ตารางกระบวนการมีตัวอธิบายไฟล์มากกว่าหนึ่งไฟล์หรือไม่ ถ้าใช่ทำไม
คำตอบ:
คำง่ายๆเมื่อคุณเปิดไฟล์ระบบปฏิบัติการจะสร้างรายการเพื่อแสดงไฟล์นั้นและเก็บข้อมูลเกี่ยวกับไฟล์ที่เปิดนั้น ดังนั้นหากมี 100 ไฟล์ที่เปิดในระบบปฏิบัติการของคุณจะมี 100 รายการในระบบปฏิบัติการ (ที่ใดที่หนึ่งในเคอร์เนล) รายการเหล่านี้แสดงเป็นจำนวนเต็มเช่น (... 100, 101, 102 .... ) หมายเลขรายการนี้เป็น file descriptor ดังนั้นมันจึงเป็นเพียงตัวเลขจำนวนเต็มที่แสดงถึงไฟล์ที่เปิดในระบบปฏิบัติการ หากกระบวนการของคุณเปิด 10 ไฟล์ตารางกระบวนการของคุณจะมี 10 รายการสำหรับตัวอธิบายไฟล์
ในทำนองเดียวกันเมื่อคุณเปิดซ็อกเก็ตเครือข่ายมันจะถูกแทนด้วยจำนวนเต็มและเรียกว่า Socket Descriptor ฉันหวังว่าคุณเข้าใจ.
/proc
ตลอดเวลา
open()
จะให้ไฟล์ descriptor 3 แก่คุณแม้ว่ากระบวนการที่กำลังรันอื่นจะมีไฟล์ descriptor 3 ดูคำนิยาม POSIX ของopen()
: "ฟังก์ชั่น open () จะส่งคืน descriptor ไฟล์สำหรับไฟล์ที่ระบุชื่อที่ต่ำที่สุด ไฟล์ descriptor ที่ยังไม่เปิดสำหรับกระบวนการนั้น " (เน้นที่เพิ่ม)
file descriptor เป็นตัวจัดการทึบแสงที่ใช้ในอินเตอร์เฟสระหว่างผู้ใช้และพื้นที่เคอร์เนลเพื่อระบุทรัพยากรของไฟล์ / ซ็อกเก็ต ดังนั้นเมื่อคุณใช้open()
หรือsocket()
(การเรียกระบบเพื่อเชื่อมต่อกับเคอร์เนล) คุณจะได้รับ file descriptor ซึ่งเป็นจำนวนเต็ม (จริง ๆ แล้วเป็นดัชนีในโครงสร้างกระบวนการ u - แต่นั่นไม่สำคัญ) ดังนั้นถ้าคุณต้องการที่จะติดต่อโดยตรงกับเคอร์เนลโดยใช้สายระบบเพื่อread()
, write()
, close()
ฯลฯ จับที่คุณใช้เป็นอธิบายไฟล์
มีเลเยอร์ของ abstraction ที่ซ้อนทับบนการเรียกของระบบซึ่งเป็นstdio
อินเตอร์เฟส สิ่งนี้มีฟังก์ชั่น / คุณสมบัติมากกว่าการเรียกระบบพื้นฐาน สำหรับอินเตอร์เฟสนี้ตัวจัดการทึบแสงที่คุณได้รับคือ a FILE*
ซึ่งถูกส่งคืนโดยการfopen()
โทร มีฟังก์ชั่นหลายที่ใช้เป็นstdio
อินเตอร์เฟซfprintf()
, fscanf()
, fclose()
ซึ่งจะมีที่จะทำให้ชีวิตของคุณง่ายขึ้น ใน C, stdin
, stdout
และstderr
มีFILE*
ซึ่งในยูนิกซ์ตามลำดับ map เพื่ออธิบายไฟล์0
, และ1
2
ได้ยินจากปากม้า: APUE (Richard Stevens)
ไปที่เคอร์เนลไฟล์ที่เปิดทั้งหมดถูกอ้างถึงโดย File Descriptors file descriptor เป็นจำนวนที่ไม่เป็นลบ
เมื่อเราเปิดไฟล์ที่มีอยู่หรือสร้างไฟล์ใหม่เคอร์เนลจะส่งคืนไฟล์ descriptor ไปยังกระบวนการ เคอร์เนลรักษาตารางของตัวอธิบายไฟล์ที่เปิดอยู่ทั้งหมดซึ่งใช้งานอยู่ การจัดสรรตัวอธิบายไฟล์โดยทั่วไปจะเรียงตามลำดับและถูกจัดสรรให้กับไฟล์เป็นตัวอธิบายไฟล์อิสระตัวถัดไปจากพูลของตัวอธิบายไฟล์อิสระ เมื่อเราปิดไฟล์ตัวอธิบายไฟล์จะได้รับการปลดปล่อยและพร้อมสำหรับการจัดสรรต่อไป
ดูภาพนี้เพื่อดูรายละเอียดเพิ่มเติม:
เมื่อเราต้องการที่จะอ่านหรือเขียนไฟล์ที่เราระบุไฟล์ที่มีการอธิบายไฟล์ที่ถูกส่งกลับโดยเปิด ()หรือสร้าง ()ฟังก์ชั่นและใช้เป็นอาร์กิวเมนต์ทั้งอ่าน ()หรือเขียน ()
มันเป็นโดยการประชุมที่ระบบ UNIX หอย บริษัท ร่วมอธิบายไฟล์ 0 พร้อมด้วยเข้ามาตรฐานของกระบวนการ, ไฟล์อธิบาย 1 ออกมาตรฐานและไฟล์อธิบาย 2 กับข้อผิดพลาดมาตรฐาน
ตัวอธิบายไฟล์มีช่วงตั้งแต่ 0 ถึง OPEN_MAX ulimit -n
ไฟล์อธิบายค่าสูงสุดสามารถรับกับ สำหรับข้อมูลเพิ่มเติมให้อ่านบทที่ 3 ของ APUE Book
osqueryi <<< echo '.all process_open_files'
ใน bash shell
คำตอบอื่น ๆ เพิ่มสิ่งที่ดี ฉันจะเพิ่มเพียง 2 เซ็นต์ของฉัน
จากวิกิพีเดียเรารู้แน่ชัดว่า file descriptor เป็นจำนวนเต็มไม่เป็นลบ สิ่งที่สำคัญที่สุดที่ฉันคิดว่าขาดหายไปคือ:
ตัวอธิบายไฟล์ถูกผูกไว้กับ ID กระบวนการ
เรารู้ว่าส่วนใหญ่อธิบายไฟล์ที่มีชื่อเสียงเป็น 0, 1 และ 2 0 สอดคล้องกับSTDIN
1 ถึงSTDOUT
และ STDERR
2
สมมติว่าใช้กระบวนการเชลล์เป็นตัวอย่างและนำไปใช้อย่างไร
ลองดูรหัสนี้
#>sleep 1000 &
[12] 14726
เราสร้างกระบวนการด้วย id 14726 (PID) ใช้lsof -p 14726
เราสามารถได้รับสิ่งนี้:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sleep 14726 root cwd DIR 8,1 4096 1201140 /home/x
sleep 14726 root rtd DIR 8,1 4096 2 /
sleep 14726 root txt REG 8,1 35000 786587 /bin/sleep
sleep 14726 root mem REG 8,1 11864720 1186503 /usr/lib/locale/locale-archive
sleep 14726 root mem REG 8,1 2030544 137184 /lib/x86_64-linux-gnu/libc-2.27.so
sleep 14726 root mem REG 8,1 170960 137156 /lib/x86_64-linux-gnu/ld-2.27.so
sleep 14726 root 0u CHR 136,6 0t0 9 /dev/pts/6
sleep 14726 root 1u CHR 136,6 0t0 9 /dev/pts/6
sleep 14726 root 2u CHR 136,6 0t0 9 /dev/pts/6
คอลัมน์ 4-th FD และคอลัมน์ถัดไป TYPE สอดคล้องกับ File Descriptor และ File Descriptor type
ค่าบางอย่างสำหรับ FD อาจเป็น:
cwd – Current Working Directory
txt – Text file
mem – Memory mapped file
mmap – Memory mapped device
แต่ตัวอธิบายไฟล์จริงอยู่ภายใต้:
NUMBER – Represent the actual file descriptor.
อักขระหลังตัวเลขคือ "1u" หมายถึงโหมดที่เปิดไฟล์ r สำหรับการอ่าน, w สำหรับการเขียน, u สำหรับการอ่านและการเขียน
TYPE ระบุประเภทของไฟล์ บางส่วนของค่าของ TYPEs คือ:
REG – Regular File
DIR – Directory
FIFO – First In First Out
แต่ตัวอธิบายไฟล์ทั้งหมดเป็น CHR - ไฟล์พิเศษของตัวละคร (หรือไฟล์อุปกรณ์ตัวอักษร)
ตอนนี้เราสามารถระบุอธิบายไฟล์สำหรับSTDIN
, STDOUT
และSTDERR
ง่ายด้วยหรือเราสามารถมองเห็นเหมือนกันถ้าเราlsof -p PID
ls /proc/PID/fd
โปรดสังเกตว่าตาราง descriptor ไฟล์ที่เคอร์เนลติดตามไม่เหมือนกับตารางไฟล์หรือตาราง inodes เหล่านี้แยกต่างหากตามคำตอบอื่น ๆ อธิบาย
คุณอาจจะถามตัวเองที่เหล่านี้อธิบายไฟล์ทางร่างกายและสิ่งที่ถูกเก็บไว้ใน/dev/pts/6
ตัวอย่างเช่น
sleep 14726 root 0u CHR 136,6 0t0 9 /dev/pts/6
sleep 14726 root 1u CHR 136,6 0t0 9 /dev/pts/6
sleep 14726 root 2u CHR 136,6 0t0 9 /dev/pts/6
ดี/dev/pts/6
อยู่ในความทรงจำอย่างหมดจด เหล่านี้ไม่ได้ไฟล์ปกติ แต่เรียกว่าแฟ้มอุปกรณ์ตัวอักษร คุณสามารถตรวจสอบเรื่องนี้ด้วย: ls -l /dev/pts/6
และพวกเขาจะเริ่มต้นด้วยในกรณีของฉันc
crw--w----
เพียงเพื่อระลึกถึง Linux ส่วนใหญ่เช่น OS กำหนดไฟล์เจ็ดประเภท:
จุดเพิ่มเติมเกี่ยวกับFile Descriptor
:
File Descriptors
(FD) เป็นจำนวนเต็มที่ไม่เป็นลบ(0, 1, 2, ...)
ที่เกี่ยวข้องกับไฟล์ที่เปิด
0, 1, 2
เป็นมาตรฐานFD 's สอดคล้องกับที่STDIN_FILENO
, STDOUT_FILENO
และSTDERR_FILENO
(ที่กำหนดไว้ในunistd.h
) เปิดได้โดยเริ่มต้นในนามของเปลือกเมื่อโปรแกรมเริ่มต้น
FD ถูกจัดสรรตามลำดับซึ่งหมายถึงค่าจำนวนเต็มที่ไม่ได้ถูกจัดสรรต่ำสุดที่เป็นไปได้
FD ของกระบวนการเฉพาะสามารถดูได้ใน/proc/$pid/fd
(บนระบบที่ใช้ Unix)
นอกเหนือจากคำตอบอื่น ๆ แล้วยูนิกซ์ก็ถือว่าทุกสิ่งเป็นระบบไฟล์ แป้นพิมพ์ของคุณเป็นไฟล์ที่อ่านได้จากมุมมองของเคอร์เนลเท่านั้น หน้าจอเป็นไฟล์เขียนอย่างเดียว ในทำนองเดียวกันโฟลเดอร์อุปกรณ์อินพุต - เอาท์พุตและอื่น ๆ ก็ถือว่าเป็นไฟล์เช่นกัน เมื่อใดก็ตามที่ไฟล์ถูกเปิดให้บอกว่าเมื่อไดรเวอร์อุปกรณ์ [สำหรับไฟล์อุปกรณ์] ร้องขอ open () หรือกระบวนการเปิดไฟล์ผู้ใช้เคอร์เนลจะจัดสรร file descriptor เป็นจำนวนเต็มที่ระบุการเข้าถึงไฟล์นั้นซึ่งเป็นการอ่านอย่างเดียว เขียนเท่านั้นเป็นต้น [สำหรับการอ้างอิง: https://en.wikipedia.org/wiki/Everything_is_a_file ]
ตัวอธิบายไฟล์ (FD):
$ ls mydir 2> errorsfile.txt
file descriptor สำหรับข้อผิดพลาดมาตรฐานคือ 2
หากไม่มีไดเร็กทอรีใดที่ชื่อเป็น mydir ดังนั้นเอาต์พุตของคำสั่งจะถูกบันทึกลงในไฟล์ errorfile.txt
โดยใช้ "2>" เราจะส่งเอาต์พุตข้อผิดพลาดไปยังไฟล์ชื่อ "errorfile อีกครั้ง txt "
ดังนั้นผลลัพธ์ของโปรแกรมจะไม่ยุ่งเหยิงกับข้อผิดพลาด
ฉันหวังว่าคุณจะได้คำตอบของคุณ
ระบบปฏิบัติการใด ๆ ที่มีกระบวนการ (p's) กำลังทำงานอยู่พูดp1, p2, p3และอื่น ๆ แต่ละกระบวนการมักจะใช้งานไฟล์อย่างต่อเนื่อง
แต่ละกระบวนการประกอบด้วยแผนผังกระบวนการ (หรือตารางกระบวนการในการใช้ถ้อยคำอื่น)
โดยทั่วไประบบปฏิบัติการจะแสดงแต่ละไฟล์ในแต่ละกระบวนการด้วยตัวเลข (กล่าวคือในแต่ละทรี / ตาราง)
ไฟล์แรกที่ใช้ในกระบวนการคือfile0ที่สองคือfile1ที่สามคือfile2และอื่น ๆ
หมายเลขใด ๆ ดังกล่าวเป็นไฟล์อธิบาย
ตัวอธิบายไฟล์มักเป็นจำนวนเต็ม (0, 1, 2 และไม่ใช่ 0.5, 1.5, 2.5)
เนื่องจากเรามักจะอธิบายกระบวนการต่าง ๆ ว่า "process-tables" และเนื่องจากตารางนั้นมีแถว (รายการ) เราสามารถพูดได้ว่าเซลล์ descriptor ของไฟล์ในแต่ละรายการใช้เพื่อแสดงรายการทั้งหมด
ในทำนองเดียวกันเมื่อคุณเปิดซ็อกเก็ตเครือข่ายจะมีตัวบ่งชี้ซ็อกเก็ต
ในระบบปฏิบัติการบางระบบคุณสามารถใช้ตัวให้คำอธิบายไฟล์หมด แต่กรณีเช่นนี้หายากมากและผู้ใช้คอมพิวเตอร์โดยเฉลี่ยไม่ควรกังวล
ตัวอธิบายไฟล์อาจเป็นแบบโกลบอล (กระบวนการ A เริ่มต้นในการพูด 0 และสิ้นสุดการพูดใน 1; โพรเซส B เริ่มพูดใน 2 และลงท้ายด้วย 3) และอื่น ๆ แต่เท่าที่ฉันรู้มักจะอยู่ในระบบปฏิบัติการสมัยใหม่ descriptors ไม่ใช่ global และแท้จริงแล้วเป็นกระบวนการเฉพาะ (กระบวนการ A เริ่มด้วย 0 และสิ้นสุดพูดใน 5 ในขณะที่กระบวนการ B เริ่มใน 0 และสิ้นสุดพูดใน 10)
นอกเหนือจากข้างต้นแล้วคำตอบที่ง่ายขึ้นทั้งหมด
หากคุณกำลังทำงานกับไฟล์ในสคริปต์ทุบตีมันจะดีกว่าที่จะใช้ตัวอธิบายไฟล์
ตัวอย่างเช่น: -
คุณต้องการอ่านและเขียนจาก / ถึงไฟล์ "test.txt"
ใช้ไฟล์ descriptor ดังแสดงด้านล่าง
FILE=$1 # give the name of file in the command line
exec 5<>$FILE # '5' here act as the file descriptor
# Reading from the file line by line using file descriptor
while read LINE; do
echo "$LINE"
done <&5
# Writing to the file using descriptor
echo "Adding the date: `date`" >&5
exec 5<&- # Closing a file descriptor
File Descriptors เป็น descriptor ของไฟล์ พวกเขาให้ลิงค์ไปยังไฟล์ ด้วยความช่วยเหลือของพวกเขาเราสามารถอ่านเขียนและเปิดไฟล์