คำตอบอื่น ๆ คือ oversimplifications แต่ละคนนำเสนอเพียงบางส่วนของเรื่องและเป็นสิ่งที่ผิดในสองประเด็น
มีสองวิธีในการติดตามไดเรกทอรีทำงาน:
- สำหรับทุกกระบวนการในโครงสร้างข้อมูลเคอร์เนลพื้นที่ซึ่งแสดงถึงกระบวนการนั้นเคอร์เนลจะเก็บ vnode สองรายการที่อ้างอิงถึง vnode ของไดเรกทอรีการทำงานและไดเรกทอรีรากสำหรับกระบวนการนั้น อ้างอิงอดีตมีการตั้งค่าโดย
chdir()
และระบบโทรหลังโดยfchdir()
chroot()
หนึ่งสามารถเห็นพวกเขาทางอ้อมใน/proc
ระบบปฏิบัติการ Linux หรือผ่านfstat
คำสั่งบน FreeBSD และไม่ชอบ:% fstat -p $$ | head -n 5
USER CMD PID FD MOUNT INUM MODE SZ | DV R / W
JdeBP zsh 92648 ข้อความ / 24958 -r-xr-xr-x 702360 r
JdeBP zsh 92648 ctty / dev 148 crw - w ---- pts / 4 rw
JdeBP zsh 92648 wd / usr / home / JdeBP 4 drwxr-xr-x 124 r
JdeBP zsh 92648 root / 4 drwxr-xr-x 35 r
%
เมื่อการจำแนกชื่อพา ธ ดำเนินการจะเริ่มต้นที่หนึ่งหรืออื่น ๆ ของ vnodes ที่อ้างอิงเหล่านั้นขึ้นอยู่กับว่าเส้นทางนั้นสัมพันธ์กันหรือสัมบูรณ์ (มีตระกูลของการ…at()
เรียกของระบบที่อนุญาตให้การแก้ไขชื่อพา ธ เริ่มต้นที่ vnode ที่อ้างอิงโดยตัวอธิบายไฟล์ open (directory) เป็นตัวเลือกที่สาม)
ใน microkernel Unices โครงสร้างข้อมูลอยู่ในพื้นที่แอปพลิเคชัน แต่หลักการของการเก็บการอ้างอิงแบบเปิดไปยังไดเรกทอรีเหล่านี้ยังคงเหมือนเดิม
- ภายในภายในเปลือกหอยเช่นซี, Korn, Bourne Again, C และ Almquist เปลือกเปลือกนอกจากนี้ติดตามการทำงานของไดเรกทอรีการทำงานโดยใช้การจัดการสตริงของตัวแปรสตริงภายใน
chdir()
มันเป็นเช่นนี้เมื่อใดก็ตามที่มีสาเหตุการเรียกร้องหากมีการเปลี่ยนแปลงชื่อพา ธ สัมพัทธ์ก็จะดำเนินการสตริงเพื่อผนวกชื่อนั้น หากมีการเปลี่ยนแปลงชื่อพา ธ สัมบูรณ์มันจะแทนที่สตริงด้วยชื่อใหม่ ในทั้งสองกรณีมันจะปรับสตริงเพื่อลบ.
และ..
ส่วนประกอบและไล่ล่าลิงก์สัญลักษณ์แทนที่พวกเขาด้วยชื่อที่เชื่อมโยงไปยัง ( นี่คือรหัสของเชลล์ Z สำหรับสิ่งนั้น)
ชื่อในตัวแปรสตริงภายในมีการติดตามโดยตัวแปรเชลล์ชื่อPWD
(หรือcwd
ใน C เชลล์) นี่คือการส่งออกตามอัตภาพเป็นตัวแปรสภาพแวดล้อม (ชื่อPWD
) ไปยังโปรแกรมที่เกิดจากเปลือก
ทั้งสองวิธีในการติดตามสิ่งต่าง ๆ นั้นได้รับการเปิดเผยโดย-P
และ-L
ตัวเลือกของคำสั่งในตัวcd
และpwd
เชลล์และโดยความแตกต่างระหว่างpwd
คำสั่งในตัวของเชลล์และทั้ง/bin/pwd
คำสั่งและคำสั่งในตัวpwd
ของสิ่งต่าง ๆ เช่น (ในหมู่อื่น ๆ ) VIM และ NeoVIM
% mkdir a; ln -sab
% (cd b; pwd; / bin / pwd; printenv PWD)
/ usr / home / JdeBP / b
/ usr / home / JdeBP / a
/ usr / home / JdeBP / b
% (cd b; pwd -P; / bin / pwd -P)
/ usr / home / JdeBP / a
/ usr / home / JdeBP / a
% (cd b; pwd -L; / bin / pwd -L)
/ usr / home / JdeBP / b
/ usr / home / JdeBP / b
% (cd -P b; pwd; / bin / pwd; printenv PWD)
/ usr / home / JdeBP / a
/ usr / home / JdeBP / a
/ usr / home / JdeBP / a
% (cd b; PWD = / hello / there / bin / pwd -L)
/ usr / home / JdeBP / a
%
อย่างที่คุณเห็น: การได้รับไดเรกทอรีทำงาน "ลอจิก" เป็นเรื่องของการดูPWD
ตัวแปรเชลล์ (หรือตัวแปรสภาพแวดล้อมหากไม่มีโปรแกรมเชลล์) ในขณะที่การรับไดเรกทอรีทำงาน "ทางกายภาพ" เป็นเรื่องของการเรียกใช้getcwd()
ฟังก์ชันไลบรารี
การทำงานของ/bin/pwd
โปรแกรมเมื่อใช้-L
ตัวเลือกนั้นค่อนข้างบอบบาง มันไม่สามารถไว้วางใจค่าของPWD
ตัวแปรสภาพแวดล้อมที่จะได้รับการถ่ายทอด ท้ายที่สุดมันไม่จำเป็นต้องถูกเรียกใช้โดยเชลล์และโปรแกรมการแทรกแซงอาจไม่ได้ใช้กลไกของเชลล์ในการทำให้PWD
ตัวแปรสภาพแวดล้อมติดตามชื่อของไดเรกทอรีทำงานเสมอ หรือบางคนอาจทำสิ่งที่ฉันทำไปที่นั่น
ดังนั้นสิ่งที่มันทำคือ (ตามมาตรฐาน POSIX บอกว่า) ตรวจสอบว่าชื่อที่กำหนดให้PWD
ผลลัพธ์เหมือนกับชื่อ.
ตามที่สามารถเห็นได้ด้วยการติดตามการโทรของระบบ:
% ln -sac
% (cd b; truss / bin / pwd -L 3> & 1 1> & 2 2> & 3 | grep -E '^ stat | __getcwd')
สถิติ ("/ usr / home / JdeBP / b", { โหมด = drwxr-xr-x, inode = 120932, ขนาด = 2, blksize = 131072}) = 0 (0x0)
สถิติ (".", {โหมด = drwxr-xr-x, inode = 120932, ขนาด = 2, blksize = 131072}) = 0 (0x0)
/ usr / home / JdeBP / b
% (cd b; PWD = / usr / local / etc truss / bin / pwd -L 3> & 1 1> & 2 2> & 3 | grep -E '^ stat | __getcwd')
สถิติ ("/ usr / local / etc" , {mode = drwxr-xr-x, inode = 14835, size = 158, blksize = 10240}) = 0 (0x0)
สถิติ (".", {โหมด = drwxr-xr-x, inode = 120932, ขนาด = 2 , blksize = 131072}) = 0 (0x0)
__getcwd ("/ usr / home / JdeBP / a", 1024) = 0 (0x0)
/ usr / home / JdeBP / a
% (cd b; PWD = / สวัสดี / มีมัด / bin / pwd -L 3> & 1 1> & 2 2> & 3 | grep -E '^ stat | __getcwd')
สถิติ ("/ hello / there", 0x7fffffffe730) ERR # 2 'ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว'
__getcwd ("/ usr / home / JdeBP / a", 1024) = 0 (0x0)
/ usr / home / JdeBP / a
% (cd b; PWD = / usr / home / JdeBP / c มัด / bin / pwd -L 3> & 1 1> & 2 2> & 3 | grep -E '^ stat | __getcwd')
stat ("/ usr / home / JdeBP / c ", {mode = drwxr-xr-x, inode = 120932, size = 2, blksize = 131072}) = 0 (0x0)
stat (". ", {mode = drwxr-xr-x, inode = 120932 , size = 2, blksize = 131072}) = 0 (0x0)
/ usr / home / JdeBP / C
%
อย่างที่คุณเห็น: มันจะเรียกgetcwd()
ก็ต่อเมื่อมันตรวจจับไม่ตรงกัน และมันสามารถถูกหลอกได้โดยการตั้งค่าPWD
เป็นสตริงที่แน่นอนชื่อไดเรกทอรีเดียวกัน แต่โดยเส้นทางที่แตกต่างกัน
getcwd()
ฟังก์ชั่นห้องสมุดเป็นเรื่องในสิทธิของตนเอง แต่เพื่อprécis:
การนำทางไปยัง..
อีกเรื่องหนึ่งในสิทธิ์ของตนเอง ข้อกำหนดเบื้องต้นอื่น: แม้ว่าไดเรกทอรีตามอัตภาพ (แม้ว่าจะเป็นที่กล่าวถึงแล้ว แต่ก็ไม่จำเป็นต้องใช้) มีเนื้อหาจริง..
ในโครงสร้างข้อมูลไดเรกทอรีบนดิสก์เคอร์เนลจะติดตามไดเรกทอรีหลักของแต่ละไดเรกทอรี vnode เองและสามารถนำทางไปยัง..
vnode ของใด ๆ ไดเรกทอรีทำงาน สิ่งนี้ค่อนข้างซับซ้อนโดยจุดเมานท์และการเปลี่ยนกลไกรูทซึ่งอยู่นอกเหนือขอบเขตของคำตอบนี้
นอกเหนือ
ที่จริงแล้ว Windows NT ทำสิ่งที่คล้ายกัน มีไดเร็กทอรีการทำงานเดียวต่อกระบวนการที่กำหนดโดยการSetCurrentDirectory()
เรียก API และติดตามต่อกระบวนการโดยเคอร์เนลผ่านตัวจัดการไฟล์ที่เปิด (ภายใน) ไปยังไดเรกทอรีนั้น และมีชุดของตัวแปรสภาพแวดล้อมที่โปรแกรม Win32 (ไม่ใช่แค่ตัวแปลคำสั่ง แต่โปรแกรม Win32 ทั้งหมด ) ใช้เพื่อติดตามชื่อของไดเรกทอรีทำงานหลายอัน (หนึ่งไดรฟ์ต่อไดรฟ์) ผนวกหรือเขียนทับพวกเขาเมื่อใดก็ตามที่พวกเขาเปลี่ยนไดเรกทอรี
โดยทั่วไปไม่เหมือนกับกรณีที่มีระบบปฏิบัติการ Unix และ Linux โปรแกรม Win32 จะไม่แสดงตัวแปรสภาพแวดล้อมเหล่านี้ให้กับผู้ใช้ บางครั้งเราสามารถเห็นพวกมันในระบบย่อยคล้าย Unix ที่ทำงานบน Windows NT รวมถึงโดยใช้คำสั่งของล่ามSET
คำสั่งด้วยวิธีการเฉพาะ
อ่านเพิ่มเติม