Trên Unix, thông thường, một tệp là một số mục trong bảng các tệp. Có nhiều loại tệp khác nhau: tệp thông thường, thiết bị, liên kết tượng trưng, cửa ra vào, đường ống, ổ cắm, thư mục ...
Số inode (mà bạn có thể thấy trong đầu ra của ls -i
) là chỉ mục trong bảng đó.
Bây giờ, bạn không truy cập các tệp bằng inode mà bằng đường dẫn . Một đường dẫn là một chuỗi các mục nhập thư mục. Bạn lưu ý chúng tôi không nói về thư mục nhưng các thư mục ở đây. Bởi vì đó là những gì một thư mục là (nghĩ về một thư mục điện thoại).
Thư mục là một loại tệp đặc biệt cung cấp tên cho một số nút. Một mục nhập thư mục là một ánh xạ từ một tên đến một nút.
Một tệp đã cho (một nút) có thể có nhiều tên trong một thư mục (giống như có thể có nhiều tên trong một số điện thoại) và cũng có thể có tên (mục) trong nhiều thư mục. Những liên kết được gọi là liên kết còn được gọi là liên kết cứng để phân biệt với liên kết mềm (một loại tệp đặc biệt là con trỏ tới đường dẫn).
Một tệp (inode) theo dõi số lượng liên kết (của các mục trong bất kỳ thư mục nào) mà nó có, do đó khi số này về 0 (khi nó được hủy liên kết từ thư mục cuối cùng, nó được tham chiếu).
Đó là số đó (số lượng liên kết) được hiển thị trong ls -l
đầu ra.
Khi một tập tin không thư mục được tạo ra lần đầu tiên (với open
hoặc creat
(hoặc bind
hoặc mknod
cho một số loại file) các cuộc gọi hệ thống), nó được thực hiện bằng cách cung cấp với một đường dẫn đến tập tin mới (như "/a/b"
). Điều xảy ra sau đó là một tệp mới và inode được phân bổ và một mục nhập mới được thêm vào thư mục được liên kết với "a"
tên trong "/"
thư mục gốc. Đó là liên kết ban đầu nên số lượng liên kết là một.
Nhiều liên kết có thể được thêm vào sau với lệnh link()
gọi hệ thống ( ln
lệnh). Và các liên kết có thể được gỡ bỏ bằng lệnh unlink()
gọi hệ thống ( rm
lệnh).
Bạn sẽ nhận thấy rằng các tệp của thư mục loại thường có số lượng liên kết lớn hơn hoặc bằng 2.
Bây giờ, khi bạn tạo một thư mục, bạn đang gọi cuộc gọi mkdir()
hệ thống. Một cái gì đó như mkdir("/a/b")
. Những gì nó làm sau đó là phân bổ một tệp mới của thư mục loại. Trong thư mục mới đó, nó tự động tạo hai mục:
"."
( chấm cho thư mục ). Đó là một liên kết đến chính nó. Vì vậy, số lượng liên kết bây giờ là 1.
".."
(đối với thư mục của thư mục ). Đó là một liên kết đến "/a"
. Vì vậy, số lượng liên kết "/a"
được tăng lên bởi một
Sau đó, thư mục mới đó được liên kết đến "/a"
(một mục nhập được thêm vào "/a"
cho nó), vì vậy số lượng liên kết của nó là 2. Nếu một "/a/b/c"
thư mục được tạo, vì ".."
mục nhập trong "/a/b/c"
, số lượng liên kết "/a/b"
sẽ trở thành 3.
Hầu hết các Unice hạn chế tạo thêm các liên kết đến một thư mục vì chúng có thể gây ra các vòng lặp có vấn đề. Khi họ cho phép một link()
thư mục, thông thường chỉ có siêu người dùng mới có thể làm điều đó.
Một số hệ thống tập tin như btrfs
khởi hành từ cấu trúc thư mục truyền thống đó. Bạn sẽ nhận thấy rằng số lượng liên kết trên các thư mục trong btrfs
các hệ thống tệp luôn luôn là một mặc dù các thư mục đó có chứa một "."
mục có cùng số inode như chính chúng trong chúng.
Thực tế là số lượng liên kết theo truyền thống là 2 cộng với số lượng các thư mục con có công dụng của nó. Ví dụ: trong:
find . -name '*.c' -print
Nếu .
không chứa các thư mục con nhưng chứa hàng triệu tệp. Bằng cách kiểm tra số lượng liên kết của .
, find
có thể biết rằng không có subir. Vì vậy, tất cả find
phải làm là đọc nội dung của thư mục và báo cáo các mục kết thúc .c
(như một grep '\.c$'
tệp trên một vài megabyte, không có vấn đề gì lớn). Nếu không, find
sẽ phải kiểm tra loại của mỗi tệp duy nhất để xem liệu có thư mục nào đi xuống trong đó không (dẫn đến nhiều lstat()
cuộc gọi hệ thống). Tất nhiên, loại tối ưu hóa này không hoạt động btrfs
(mặc dù trong các phiên bản Linux hiện đại, loại tệp cũng được lưu trong mục nhập thư mục cho một số hệ thống tệp (bao gồm btrfs
) và được trả về bởi lệnh getdents(2)
gọi hệ thống được sử dụng để truy xuất danh sách các mục nhập trong một thư mục, vì vậylstat
vẫn không cần thiết).