⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fileio.txt

📁 开放源码实时操作系统源码.
💻 TXT
📖 第 1 页 / 共 2 页
字号:
File System Support Infrastructure
==================================

Nick Garnett
v0.2


This document describes the filesystem infrastructure provided in
eCos. This is implemented by the FILEIO package and provides POSIX
compliant file and IO operations together with the BSD socket
API. These APIs are described in the relevant standards and original
documentation and will not be described here. This document is,
instead, concerned with the interfaces presented to client
filesystems and network protocol stacks.

The FILEIO infrastructure consist mainly of a set of tables containing
pointers to the primary interface functions of a file system. This
approach avoids problems of namespace pollution (several filesystems
can have a function called read(),so long as they are static). The
system is also structured to eliminate the need for dynamic memory
allocation.

New filesystems can be written directly to the interfaces described
here. Existing filesystems can be ported very easily by the
introduction of a thin veneer porting layer that translates FILEIO
calls into native filesystem calls. 

The term filesystem should be read fairly loosely in this
document. Object accessed through these interfaces could equally be
network protocol sockets, device drivers, fifos, message queues or any
other object that can present a file-like interface.

    
File System Table
-----------------

The filesystem table is an array of entries that describe each
filesystem implementation that is part of the system image. Each
resident filesystem should export an entry to this table using the
FSTAB_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 filesystem
implementation. 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 to
be used when accessing this filesystem. It will be described in more
detail in the "Synchronization" section.

The remaining fields are pointers to functions that implement
filesystem operations that apply to files and directories as whole
objects. The operation implemented by each function should be obvious
from the names, with a few exceptions.

The _opendir_ function opens a directory for reading. See the section
on Directories later for details.

The _getinfo_ and _setinfo_ functions provide support for various
minor control and information functions such as pathconf() and
access().

With the exception of the _mount_ and _umount_ functions, all of these
functions take three standard arguments, a pointer to a mount table
entry (see later) a directory pointer (also see later) and a file name
relative to the directory. These should be used by the filesystem to
locate 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 other
components) may export static entries to the table using the
MTAB_ENTRY() macro. Alternatively, new entries may be installed at run
time using the mount() function. Both types of entry may be unmounted
with 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 translate
rooted filenames (filenames that begin with "/") into the correct
filesystem. When a file name that begins with "/" is submitted, it is
matched against the _name_ fields of all valid mount table
entries. The entry that yields the longest match terminating before a
"/", or end of string, wins and the appropriate function from the
filesystem table entry is then passed the remainder of the file name
together 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 following
entries:

	{ "/",    "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 filesystem
while an open of "/bar/bundy" would be directed to the hard disc MSDOS
filesystem. Opening "/dev/tty0" would be directed to the device
management filesystem for lookup in the device table.

Unrooted file names (those that do not begin with a '/') are passed
straight to the current directory. The current directory is
represented by a pair consisting of a mount table entry and a
directory pointer.

The _fsname_ field points to a string that should match the _name_
field of the implementing filesystem. During initialization the mount
table is scanned and the _fsname_ entries looked up in the
filesystem table. For each match, the filesystem's _mount_ function
is called and if successful the mount table entry is marked as valid
and the _fs_ pointer installed.

The _devname_ field contains the name of the device that this
filesystem is to use. This may match an entry in the device table (see
later) or may be a string that is specific to the filesystem if it has
its own internal device drivers.

The _data_ field is a private data value. This may be installed either
statically when the table entry is defined, or may be installed during
the _mount_ operation.

The _valid_ field indicates whether this mount point has actually been
mounted successfully. Entries with a false _valid_ field are ignored
when searching for a name match.

The _fs_ field is installed after a successful mount operation to
point to the implementing filesystem.

The _root_ field contains a directory pointer value that the
filesystem can interpret as the root of its directory tree. This is
passed as the _dir_ argument of filesystem functions that operate on
rooted 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 file
object. These are allocated from an array of available file
objects. User code accesses these open file objects via a second array
of pointers which is indexed by small integer offsets. This gives the
usual Unix file descriptor functionality, complete with the various
duplication 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 the
bits from the open call (defined by CYG_FILE_MODE_MASK).

The _f_ucount_ field contains a use count that controls when a file
will be closed. Each duplicate in the file descriptor array counts for
one reference here and it is also incremented around each I/O
operation.

The _f_type_ field indicates the type of the underlying file
object. 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 the
implementing filesystem. Its use is described in the "Synchronization"
section later.

The _f_offset_ field records the current file position. It is the
responsibility of the file operation functions to keep this field up
to date.

The _f_data_ field contains private data placed here by the underlying
filesystem. Normally this will be a pointer to or handle on the
filesystem object that implements this file.

The _f_xops_ field contains a pointer to any extra type specific
operation functions. For example, the socket I/O system installs a
pointer to a table of functions that implement the standard socket
operations.

The _f_mte_ field contains a pointer to the parent mount table entry
for this file. It is used mainly to implement the synchronization
protocol. This may contain a pointer to some other data structure in
file objects not derived from a filesystem.

The _f_ops_ field contains a pointer to a table of file I/O
operations. 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 what
their 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 UIO
structure:

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 transfer
operation. It provides support for scatter/gather operations and
records the progress of any data transfer. It is also compatible with
the 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 the
filesystem open operation to initialize all the fields of the object
except 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 + -