K&R interface for reading directories: superfluous DIR structure?

匿名 (未验证) 提交于 2019-12-03 01:34:02

问题:

In the 2nd edition of "The C Programming Language" by Kernighan and Ritchie they implement a simplified version of the UNIX command ls (section 8.6 "Example - Listing Directories", p. 179). For this purpose they create the following interface which provides a system-independent access to the name and inode number of the files stored in a directory.

#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); 

Then they implement this interface for Version 7 and System V UNIX systems.

  • opendir() basically uses the system call open() to open a directory and malloc() to allocate space for a DIR structure. The file descriptor returned by open() is then stored in the variable fd of that DIR. Nothing is stored in the Dirent component.

  • readdir() uses the system call read() to get the next (system-dependent) directory entry of an opened directory and copies the so obtained inode number and filename into a static Dirent structure (to which a pointer is returned). The only information needed by readdir() is the file descriptor stored in the DIR structure.

Now to my question: What is the point of having a DIR structure? If my understanding of this program is correct, the Dirent component of DIR is never used, so why not replace the whole structure with a file descriptor and directly use open() and close()?

Thanks.

Ps: I am aware that on modern UNIX systems read() can no longer be used on directories (I have tried out this program on Ubuntu 10.04), but I still want to make sure that I have not overlooked something important in this example.

回答1:

From K&R:

Regrettably, the format and precise contents of a directory are not the same on all versions of the system. So we will divide the task into two pieces to try to isolate the non-portable parts. The outer level defines a structure called a Dirent and three routines opendir, readdir, and closedir to provide system-independent access to the name and inode number in a directory entry.

So the reason is portability. They want to define an interface that can survive on systems that have different stat structs or nonstandard open() and close(). They go on to build a bunch of reusable tools around it, which don't even care if they're on a Unix-like system. That's the point of wrappers.

Maybe it's not used because they started out by defining their data structures (with a Dirent inside DIR) but ended up not using it. Keeping data structures grouped like that is good design.



回答2:

It is so they don't have to allocate memory for the Dirent structure that is returned by readdir. This way they can reuse the Dirent between subsiquent calls to readdir.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!