📄 fileio.txt
字号:
File System Support Infrastructure==================================Nick Garnettv0.2This document describes the filesystem infrastructure provided ineCos. This is implemented by the FILEIO package and provides POSIXcompliant file and IO operations together with the BSD socketAPI. These APIs are described in the relevant standards and originaldocumentation and will not be described here. This document is,instead, concerned with the interfaces presented to clientfilesystems and network protocol stacks.The FILEIO infrastructure consist mainly of a set of tables containingpointers to the primary interface functions of a file system. Thisapproach avoids problems of namespace pollution (several filesystemscan have a function called read(),so long as they are static). Thesystem is also structured to eliminate the need for dynamic memoryallocation.New filesystems can be written directly to the interfaces describedhere. Existing filesystems can be ported very easily by theintroduction of a thin veneer porting layer that translates FILEIOcalls into native filesystem calls. The term filesystem should be read fairly loosely in thisdocument. Object accessed through these interfaces could equally benetwork protocol sockets, device drivers, fifos, message queues or anyother object that can present a file-like interface. File System Table-----------------The filesystem table is an array of entries that describe eachfilesystem implementation that is part of the system image. Eachresident filesystem should export an entry to this table using theFSTAB_ENTRY() macro.The table entries are described by the following structure:struct cyg_fstab_entry{ const char *name; // filesystem name CYG_ADDRWORD data; // private data value cyg_uint32 syncmode; // synchronization mode int (*mount) ( cyg_fstab_entry *fste, cyg_mtab_entry *mte ); int (*umount) ( cyg_mtab_entry *mte ); int (*open) ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, int mode, cyg_file *fte ); int (*unlink) ( cyg_mtab_entry *mte, cyg_dir dir, const char *name ); int (*mkdir) ( cyg_mtab_entry *mte, cyg_dir dir, const char *name ); int (*rmdir) ( cyg_mtab_entry *mte, cyg_dir dir, const char *name ); int (*rename) ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1, cyg_dir dir2, const char *name2 ); int (*link) ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1, cyg_dir dir2, const char *name2, int type ); int (*opendir) ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, cyg_file *fte ); int (*chdir) ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, cyg_dir *dir_out ); int (*stat) ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, struct stat *buf); int (*getinfo) ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, int key, char *buf, int len ); int (*setinfo) ( cyg_mtab_entry *mte, cyg_dir dir, const char *name, int key, char *buf, int len );};The _name_ field points to a string that identifies this filesystemimplementation. Typical values might be "romfs", "msdos", "ext2" etc.The _data_ field contains any private data that the filesystem needs,perhaps the root of its data structures.The _syncmode_ field contains a description of the locking protocol tobe used when accessing this filesystem. It will be described in moredetail in the "Synchronization" section.The remaining fields are pointers to functions that implementfilesystem operations that apply to files and directories as wholeobjects. The operation implemented by each function should be obviousfrom the names, with a few exceptions.The _opendir_ function opens a directory for reading. See the sectionon Directories later for details.The _getinfo_ and _setinfo_ functions provide support for variousminor control and information functions such as pathconf() andaccess().With the exception of the _mount_ and _umount_ functions, all of thesefunctions take three standard arguments, a pointer to a mount tableentry (see later) a directory pointer (also see later) and a file namerelative to the directory. These should be used by the filesystem tolocate the object of interest.Mount Table-----------The mount table records the filesystems that are actually active.These can be seen as being analogous to mount points in Unix systems.There are two sources of mount table entries. Filesystems (or othercomponents) may export static entries to the table using theMTAB_ENTRY() macro. Alternatively, new entries may be installed at runtime using the mount() function. Both types of entry may be unmountedwith the umount() function.A mount table entry has the following structure:struct cyg_mtab_entry{ const char *name; // name of mount point const char *fsname; // name of implementing filesystem const char *devname; // name of hardware device CYG_ADDRWORD data; // private data value cyg_bool valid; // Valid entry? cyg_fstab_entry *fs; // pointer to fstab entry cyg_dir root; // root directory pointer};The _name_ field identifies the mount point. This is used to translaterooted filenames (filenames that begin with "/") into the correctfilesystem. When a file name that begins with "/" is submitted, it ismatched against the _name_ fields of all valid mount tableentries. The entry that yields the longest match terminating before a"/", or end of string, wins and the appropriate function from thefilesystem table entry is then passed the remainder of the file nametogether with a pointer to the table entry and the value of the _root_field as the directory pointer.For example, consider a mount table that contains the followingentries: { "/", "msdos", "/dev/hd0", ... } { "/fd", "msdos", "/dev/fd0", ... } { "/rom", "romfs", "", ... } { "/tmp", "ramfs", "", ... } { "/dev", "devfs", "", ... }An attempt to open "/tmp/foo" would be directed to the RAM filesystemwhile an open of "/bar/bundy" would be directed to the hard disc MSDOSfilesystem. Opening "/dev/tty0" would be directed to the devicemanagement filesystem for lookup in the device table.Unrooted file names (those that do not begin with a '/') are passedstraight to the current directory. The current directory isrepresented by a pair consisting of a mount table entry and adirectory pointer.The _fsname_ field points to a string that should match the _name_field of the implementing filesystem. During initialization the mounttable is scanned and the _fsname_ entries looked up in thefilesystem table. For each match, the filesystem's _mount_ functionis called and if successful the mount table entry is marked as validand the _fs_ pointer installed.The _devname_ field contains the name of the device that thisfilesystem is to use. This may match an entry in the device table (seelater) or may be a string that is specific to the filesystem if it hasits own internal device drivers.The _data_ field is a private data value. This may be installed eitherstatically when the table entry is defined, or may be installed duringthe _mount_ operation.The _valid_ field indicates whether this mount point has actually beenmounted successfully. Entries with a false _valid_ field are ignoredwhen searching for a name match.The _fs_ field is installed after a successful mount operation topoint to the implementing filesystem.The _root_ field contains a directory pointer value that thefilesystem can interpret as the root of its directory tree. This ispassed as the _dir_ argument of filesystem functions that operate onrooted filenames. This field must be initialized by the filesystem's_mount_ function.File Table----------Once a file has been opened it is represented by an open fileobject. These are allocated from an array of available fileobjects. User code accesses these open file objects via a second arrayof pointers which is indexed by small integer offsets. This gives theusual Unix file descriptor functionality, complete with the variousduplication mechanisms.A file table entry has the following structure:struct CYG_FILE_TAG{ cyg_uint32 f_flag; /* file state */ cyg_uint16 f_ucount; /* use count */ cyg_uint16 f_type; /* descriptor type */ cyg_uint32 f_syncmode; /* synchronization protocol */ struct CYG_FILEOPS_TAG *f_ops; /* file operations */ off_t f_offset; /* current offset */ CYG_ADDRWORD f_data; /* file or socket */ CYG_ADDRWORD f_xops; /* extra type specific ops */ cyg_mtab_entry *f_mte; /* mount table entry */};The _f_flag_ field contains some FILEIO control bits and some of thebits from the open call (defined by CYG_FILE_MODE_MASK).The _f_ucount_ field contains a use count that controls when a filewill be closed. Each duplicate in the file descriptor array counts forone reference here and it is also incremented around each I/Ooperation.The _f_type_ field indicates the type of the underlying fileobject. Some of the possible values here are CYG_FILE_TYPE_FILE,CYG_FILE_TYPE_SOCKET or CYG_FILE_TYPE_DEVICE.The _f_syncmode_ field is copied from the _syncmode_ field of theimplementing filesystem. Its use is described in the "Synchronization"section later.The _f_offset_ field records the current file position. It is theresponsibility of the file operation functions to keep this field upto date.The _f_data_ field contains private data placed here by the underlyingfilesystem. Normally this will be a pointer to or handle on thefilesystem object that implements this file.The _f_xops_ field contains a pointer to any extra type specificoperation functions. For example, the socket I/O system installs apointer to a table of functions that implement the standard socketoperations.The _f_mte_ field contains a pointer to the parent mount table entryfor this file. It is used mainly to implement the synchronizationprotocol. This may contain a pointer to some other data structure infile objects not derived from a filesystem.The _f_ops_ field contains a pointer to a table of file I/Ooperations. This has the following structure:struct CYG_FILEOPS_TAG{ int (*fo_read) (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio); int (*fo_write) (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio); int (*fo_lseek) (struct CYG_FILE_TAG *fp, off_t *pos, int whence ); int (*fo_ioctl) (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com, CYG_ADDRWORD data); int (*fo_select) (struct CYG_FILE_TAG *fp, int which, CYG_ADDRWORD info); int (*fo_fsync) (struct CYG_FILE_TAG *fp, int mode ); int (*fo_close) (struct CYG_FILE_TAG *fp); int (*fo_fstat) (struct CYG_FILE_TAG *fp, struct stat *buf ); int (*fo_getinfo) (struct CYG_FILE_TAG *fp, int key, char *buf, int len ); int (*fo_setinfo) (struct CYG_FILE_TAG *fp, int key, char *buf, int len );};It should be obvious from the names of most of these functions whattheir responsibilities are. The _fo_getinfo_ and _fo_setinfo_function, like their counterparts in the filesystem structure,implement minor control and info functions such as fpathconf().The second argument to _fo_read_ and _fo_write_ is a pointer to a UIOstructure:struct CYG_UIO_TAG{ struct CYG_IOVEC_TAG *uio_iov; /* pointer to array of iovecs */ int uio_iovcnt; /* number of iovecs in array */ off_t uio_offset; /* offset into file this uio corresponds to */ ssize_t uio_resid; /* residual i/o count */ enum cyg_uio_seg uio_segflg; /* see above */ enum cyg_uio_rw uio_rw; /* see above */};struct CYG_IOVEC_TAG{ void *iov_base; /* Base address. */ ssize_t iov_len; /* Length. */};This structure encapsulates the parameters of any data transferoperation. It provides support for scatter/gather operations andrecords the progress of any data transfer. It is also compatible withthe I/O operations of any BSD-derived network stacks and filesystems.When a file is opened (or a file object created by some other means,such as socket() or accept()) it is the responsibility of thefilesystem open operation to initialize all the fields of the objectexcept the _f_ucount_, _f_syncmode_ and _f_mte_ fields. Since the_f_flag_ field will already contain bits belonging to the FILEIO
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -