คำตอบอื่น ๆ คือ 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คำสั่งด้วยวิธีการเฉพาะ
อ่านเพิ่มเติม