11.5. Files and File DescriptorsAt the system call level, Mac OS X represents open files in a process by using integral file descriptors, each of which is an index into the process's file descriptor table in the kernel. When a user program uses a file descriptor in a system call, the kernel uses the file descriptor to find the corresponding file data structure, which in turn contains informationsuch as a function-pointer tableusing which I/O can be performed on the file. This scenario is conceptually the same across Unix and Unix-like systems. However, the specific data structures involved are often different. Figure 1111 shows the primary file-related kernel data structures in Mac OS X. Figure 1111. How a file descriptor leads to a file in Mac OS XLet us assume there is a file descriptor called fd in a process with ID pid. Each process structure (struct proc) contains a pointer (p_fd) to a filedesc structure, which holds information about the process's open files. In particular, it contains pointers to two arrays: an array of fileproc structures (fd_ofiles) and an array of open file flags (fd_ofileflags). In the case of our file descriptor fd, the elements with index fd in both these arrays will correspond to the file fd represents. If a descriptor is released (because it has no remaining references), that index in both arrays becomes free. The fd_freefile field of the filedesc structure is used to store a hint that the kernel uses while searching for a free file descriptor. As Figure 1111 shows, each entry of the fd_ofiles array is a fileproc structure. The fg_ops and fg_data fields of this structure point to data structures whose contents depend on the file descriptor's type. Besides files, the kernel uses file descriptors to represent several types of entities, which are listed in Table 111. Figure 1111 assumes that fd corresponds to a file. Therefore, fg_ops points to a table of vnode operations[6] (the global data structure vnops), whereas fg_data points to a vnode structure. If the descriptor represented a socket instead, fg_ops would point to a table of socket operations, and fg_data would point to a socket structure.
|