2010-09-17 25 views
5

Trong ấn bản thứ hai của "Ngôn ngữ lập trình C" bởi Kernighan và Ritchie, chúng triển khai phiên bản đơn giản của lệnh UNIX ls (phần 8.6 "Ví dụ - Danh bạ", tr. 179). Với mục đích này, họ tạo ra giao diện sau cung cấp truy cập độc lập hệ thống vào tên và số inode của các tệp được lưu trữ trong một thư mục.Giao diện K & R để đọc các thư mục: cấu trúc DIR thừa?

#define NAME_MAX 14 /* longest filename component; */ 
           /* system dependent */ 

typedef struct {  /* portable director-entry */ 
    long ino;     /* inode number */ 
    char name[NAME_MAX+1]; /* name + '\0' terminator */ 
} Dirent; 

typedef struct {  /* minimal DIR: no buffering, etc. */ 
    int fd;     /* file descriptor for directory */ 
    Dirent d;     /* the directory entry */ 
} DIR; 

DIR *opendir(char *dirname); 
Dirent *readdir(DIR *dfd); 
void closedir(DIR *dfd); 

Sau đó, họ triển khai giao diện này cho phiên bản 7 và hệ thống V UNIX.

  • opendir() cơ bản sử dụng hệ thống gọi open() để mở một thư mục và malloc() phân bổ không gian cho một cấu trúc DIR. Trình mô tả tệp được trả về trước open() sau đó được lưu trữ trong biến số fd trong số đó DIR. Không có gì được lưu trữ trong thành phần Dirent .

  • readdir() sử dụng cuộc gọi hệ thống read() để có được sự xâm nhập thư mục (hệ thống phụ thuộc vào) tiếp theo của một thư mục mở ra và bản sao cái thu được số inode và filename thành một Dirent cấu trúc tĩnh (để đó một con trỏ được trả về). Thông tin chỉ cần thiết bởi readdir() là bộ mô tả tệp được lưu trữ trong cấu trúc DIR.

Bây giờ câu hỏi của tôi: điểm của việc có một cấu trúc DIR là gì? Nếu hiểu biết của tôi về chương trình này là chính xác thì thành phần Dirent của DIR không bao giờ được sử dụng, vậy tại sao không thay thế toàn bộ cấu trúc bằng bộ mô tả tệp và trực tiếp sử dụng open()close()?

Cảm ơn.

Ps: Tôi biết rằng trên hệ thống UNIX hiện đại read() không còn có thể được sử dụng trên thư mục nữa (tôi đã thử chương trình này trên Ubuntu 10.04), nhưng tôi vẫn muốn đảm bảo rằng tôi đã không bỏ qua điều gì đó quan trọng trong thí dụ.

Trả lời

4

Từ K & R:

Đáng tiếc, định dạng và chính xác nội dung của một thư mục không giống nhau trên tất cả các phiên bản của hệ thống. Vì vậy, chúng tôi sẽ chia nhiệm vụ thành hai phần để cố gắng cách ly các bộ phận không di động. Mức bên ngoài định nghĩa một cấu trúc gọi là Dirent và ba thói quen opendir, readdir, và closedir để cung cấp truy cập hệ thống độc lập với tên tuổi và inode số trong một entry thư mục.

Vì vậy, lý do là tính di động. Họ muốn xác định giao diện có thể tồn tại trên các hệ thống có cấu trúc stat khác nhau hoặc không chuẩn open()close(). Họ tiếp tục xây dựng một loạt các công cụ có thể tái sử dụng xung quanh nó, mà thậm chí không quan tâm nếu họ đang ở trên một hệ thống giống Unix. Đó là điểm của hàm bao.

Có thể nó không được sử dụng vì chúng bắt đầu bằng cách xác định cấu trúc dữ liệu của chúng (với Dirent bên trong DIR) nhưng cuối cùng không sử dụng nó. Giữ cấu trúc dữ liệu được nhóm lại như vậy là thiết kế tốt.

+0

Tính di động cũng là phỏng đoán đầu tiên của tôi nhưng sau khi suy nghĩ về điều đó, tôi không thấy làm thế nào 'DIR' có thể đóng góp cho điều này. Thông tin liên quan duy nhất mà nó có thể truyền cho 'readdir()' là bộ mô tả tập tin. Tôi vẫn không thấy việc sử dụng thành phần 'Dirent' trong' DIR'. Bất kể hệ thống nào, bất kỳ sự thực hiện nào của 'readdir()' đều có thể có một 'Dirent' tĩnh để nó có thể trả về một con trỏ, vì vậy đây không phải là một vấn đề về tính di động. Đúng là 'dirwalk()' truy cập nội dung của một 'Dirent', nhưng đây là một phần tử tĩnh từ' readdir() ', không phải là một trong' DIR'. Tôi có thiếu gì đó không? – qfab

+1

Xin chào, có vẻ như bạn đã đúng. Tôi đoán là họ bắt đầu bằng cách xác định cấu trúc dữ liệu của họ (với một 'Dirent' bên trong 'DIR') nhưng cuối cùng không sử dụng nó. Nhóm các dữ liệu liên quan với nhau trong các cấu trúc là juju tốt. Một bài tập tốt sẽ là viết lại mã để sử dụng 'DIR.d' thay vì có người gọi' readdir() 'có con trỏ' Dirent' của riêng họ. – nmichaels

+0

Vâng, đây là một lời giải thích hợp lý. Nhưng xem xét cuốn sách đã được xuất bản hơn 20 năm trước (ấn bản thứ 2), thật lạ lùng rằng một cái gì đó như thế này không được đề cập trong [errata] (http://cm.bell-labs.com/cm/cs/cbook/ 2ediffs.html). – qfab

0

Vì vậy, chúng không phải cấp phát bộ nhớ cho cấu trúc Dirent được trả về bởi readdir. Bằng cách này, họ có thể tái sử dụng Dirent giữa các cuộc gọi độc lập để readdir.

+0

Nhưng chúng không phải phân bổ bộ nhớ vì 'readdir()' lưu trữ 'Dirent' là một biến tĩnh. – qfab

+2

@qfab: Có nhưng đó thực sự là một thiết kế tồi. Việc thực hiện được cải thiện giả thuyết sẽ đặt bộ đệm bên trong cấu trúc 'DIR' để đọc đồng thời nhiều thư mục sẽ không che giấu dữ liệu (và vì vậy nó sẽ là an toàn thread miễn là bạn không sử dụng một đối tượng' DIR' đơn lẻ nào nhiều hơn một luồng tại một thời điểm). Tôi hy vọng việc triển khai hiện đại làm điều này; tôi chắc chắn không. –

Các vấn đề liên quan