Các câu trả lời khác là quá đơn giản, mỗi phần chỉ trình bày các phần của câu chuyện và sai ở một vài điểm.
Có hai cách để theo dõi thư mục làm việc:
- Đối với mọi quy trình, trong cấu trúc dữ liệu không gian nhân đại diện cho quy trình đó, nhân lưu trữ hai tham chiếu vnode đến vnodes của thư mục làm việc và thư mục gốc cho quy trình đó. Tham chiếu trước được thiết lập bởi các cuộc gọi
chdir()
và fchdir()
hệ thống, sau này bởi chroot()
. Người ta có thể thấy chúng gián tiếp /proc
trên các hệ điều hành Linux hoặc thông qua fstat
lệnh trên FreeBSD và tương tự:% fstat -p $$ | đầu -n 5
NGƯỜI DÙNG CMD PID FD MOUNT INUM MODE SZ | DV R / W
JdeBP zsh 92648 văn bản / 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
%
Khi độ phân giải tên đường dẫn hoạt động, nó bắt đầu ở một hoặc một trong các vnodes được tham chiếu, tùy theo đường dẫn là tương đối hay tuyệt đối. (Có một nhóm các …at()
cuộc gọi hệ thống cho phép bắt đầu phân giải tên đường dẫn tại vnode được tham chiếu bởi một bộ mô tả tệp mở (thư mục) dưới dạng tùy chọn thứ ba.)
Trong microkernel Unices cấu trúc dữ liệu nằm trong không gian ứng dụng, nhưng nguyên tắc giữ các tham chiếu mở đến các thư mục này vẫn giữ nguyên.
- Bên trong, trong các shell như Z, Korn, Bourne Again, C và Almquist, shell cũng theo dõi thư mục làm việc bằng cách sử dụng thao tác chuỗi của biến chuỗi bên trong. Nó làm điều này bất cứ khi nào nó có lý do để gọi
chdir()
.Nếu một thay đổi thành một tên đường dẫn tương đối, nó sẽ thao tác chuỗi để nối thêm tên đó. Nếu một thay đổi thành một tên đường dẫn tuyệt đối, nó sẽ thay thế chuỗi bằng tên mới. Trong cả hai trường hợp, nó điều chỉnh chuỗi để loại bỏ .
và ..
các thành phần và theo đuổi các liên kết tượng trưng thay thế chúng bằng các tên được liên kết với chúng. ( Ví dụ, đây là mã Z shell cho điều đó .)
Tên trong biến chuỗi bên trong được theo dõi bởi biến shell có tên PWD
(hoặc cwd
trong shell C). Điều này thường được xuất dưới dạng một biến môi trường (được đặt tên PWD
) cho các chương trình được sinh ra bởi trình bao.
Hai phương pháp theo dõi sự vật này được tiết lộ bởi -P
và -L
các tùy chọn cho các lệnh tích hợp cd
và pwd
shell, và bởi sự khác biệt giữa các pwd
lệnh tích hợp của shell và cả /bin/pwd
lệnh và pwd
lệnh tích hợp của những thứ như (giữa các lệnh khác) VIM và NeoVIM.
% mkdir a; ln -sab
% (cd b; pwd; / bin / pwd; printenv PWD)
/ usr / nhà / JdeBP / b
/ usr / nhà / JdeBP / a
/ usr / nhà / JdeBP / b
% (cd b; pwd -P; / bin / pwd -P)
/ usr / nhà / JdeBP / a
/ usr / nhà / JdeBP / a
% (cd b; pwd -L; / bin / pwd -L)
/ usr / nhà / JdeBP / b
/ usr / nhà / JdeBP / b
% (cd -P b; pwd; / bin / pwd; printenv PWD)
/ usr / nhà / JdeBP / a
/ usr / nhà / JdeBP / a
/ usr / nhà / JdeBP / a
% (cd b; PWD = / xin chào / có / bin / pwd -L)
/ usr / nhà / JdeBP / a
%
Như bạn có thể thấy: có được thư mục làm việc "logic" là vấn đề xem xét PWD
biến shell (hoặc biến môi trường nếu không phải là chương trình shell); trong khi đó có được thư mục làm việc "vật lý" là vấn đề gọi getcwd()
hàm thư viện.
Hoạt động của /bin/pwd
chương trình khi -L
tùy chọn được sử dụng là hơi tinh tế. Nó không thể tin tưởng vào giá trị của PWD
biến môi trường mà nó được thừa hưởng. Rốt cuộc, nó không cần phải được gọi bởi shell và các chương trình can thiệp có thể không thực hiện cơ chế của shell để PWD
biến biến môi trường luôn theo dõi tên của thư mục làm việc. Hoặc ai đó có thể làm những gì tôi đã làm chỉ ở đó.
Vì vậy, những gì nó làm là (như tiêu chuẩn POSIX nói) kiểm tra xem tên được đưa ra có PWD
mang lại điều tương tự như tên .
, như có thể thấy với dấu vết cuộc gọi hệ thống:
% ln -sac
% (cd b; truss / bin / pwd -L 3> & 1 1> & 2 2> & 3 | grep -E '^ stat | __getcwd')
stat ("/ usr / home / JdeBP / b", { 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 / nhà / JdeBP / b
% (cd b; PWD = / usr / local / etc truss / bin / pwd -L 3> & 1 1> & 2 2> & 3 | grep -E '^ stat | __getcwd')
stat ("/ usr / local / etc" , {mode = drwxr-xr-x, inode = 14835, size = 158, blksize = 10240}) = 0 (0x0)
stat (".", {mode = drwxr-xr-x, inode = 120932, size = 2 , blksize = 131072}) = 0 (0x0)
__getcwd ("/ usr / nhà / JdeBP / a", 1024) = 0 (0x0)
/ usr / nhà / JdeBP / a
% (cd b; PWD = / hello / there truss / bin / pwd -L 3> & 1 1> & 2 2> & 3 | grep -E '^ stat | __getcwd')
stat ("/ hello / there", 0x7fffffffe730) ERR # 2 'Không có tệp hoặc thư mục như vậy'
__getcwd ("/ usr / home / JdeBP / a", 1024) = 0 (0x0)
/ usr / nhà / JdeBP / a
% (cd b; PWD = / usr / home / JdeBP / c truss / 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 , kích thước = 2, blksize = 131072}) = 0 (0x0)
/ usr / nhà / JdeBP / c
%
Như bạn có thể thấy: nó chỉ gọi getcwd()
nếu phát hiện sự không phù hợp; và nó có thể bị đánh lừa bằng cách đặt PWD
thành một chuỗi thực sự đặt tên cho cùng một thư mục, nhưng theo một tuyến khác.
Các getcwd()
chức năng thư viện là một chủ đề theo đúng nghĩa của nó. Nhưng để trang trí:
Điều hướng đến ..
một lần nữa là một chủ đề theo đúng nghĩa của nó. Một kiểu trang trí khác: Mặc dù các thư mục theo quy ước (mặc dù đã được ám chỉ, nhưng điều này là không bắt buộc) có chứa một thực tế ..
trong cấu trúc dữ liệu thư mục trên đĩa, kernel theo dõi thư mục mẹ của mỗi thư mục vnode và do đó có thể điều hướng đến ..
vnode của bất kỳ thư mục làm việc. Điều này hơi phức tạp bởi các điểm gắn kết và cơ chế gốc đã thay đổi, nằm ngoài phạm vi của câu trả lời này.
Qua một bên
Windows NT trong thực tế làm một điều tương tự. Có một thư mục làm việc cho mỗi tiến trình, được đặt bởi lệnh SetCurrentDirectory()
gọi API và được theo dõi trên mỗi tiến trình bởi kernel thông qua một tệp xử lý tệp mở (bên trong) đến thư mục đó; và có một tập hợp các biến môi trường mà các chương trình Win32 (không chỉ là trình thông dịch lệnh, mà tất cả các chương trình Win32) sử dụng để theo dõi tên của nhiều thư mục làm việc (một trên mỗi ổ đĩa), thêm vào hoặc ghi đè chúng bất cứ khi nào chúng thay đổi thư mục.
Thông thường, không giống như các hệ điều hành Unix và Linux, các chương trình Win32 không hiển thị các biến môi trường này cho người dùng. Tuy nhiên, đôi khi người ta có thể thấy chúng trong các hệ thống con giống như Unix chạy trên Windows NT, cũng như bằng cách sử dụng các lệnh của trình thông dịch SET
lệnh theo một cách cụ thể.
đọc thêm