📄 fileio.sgml
字号:
<!-- {{{ Banner -->
<!-- =============================================================== -->
<!-- -->
<!-- fileio.sgml -->
<!-- -->
<!-- eCos Generic File I/O package documentation -->
<!-- -->
<!-- =============================================================== -->
<!-- ####COPYRIGHTBEGIN#### -->
<!-- -->
<!-- =============================================================== -->
<!-- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. -->
<!-- This material may be distributed only subject to the terms -->
<!-- and conditions set forth in the Open Publication License, v1.0 -->
<!-- or later (the latest version is presently available at -->
<!-- http://www.opencontent.org/openpub/) -->
<!-- Distribution of the work or derivative of the work in any -->
<!-- standard (paper) book form is prohibited unless prior -->
<!-- permission obtained from the copyright holder -->
<!-- =============================================================== -->
<!-- -->
<!-- ####COPYRIGHTEND#### -->
<!-- =============================================================== -->
<!-- #####DESCRIPTIONBEGIN#### -->
<!-- -->
<!-- ####DESCRIPTIONEND#### -->
<!-- =============================================================== -->
<!-- }}} -->
<part id="fileio">
<title>File System Support Infrastructure</title>
<!-- {{{ Introduction -->
<chapter id="fileio-intro">
<title>Introduction</title>
<para>
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. See <xref
linkend="posix-standard-support"> for details of which parts of the
POSIX standard are supported.
</para>
<para>
This document is concerned with the interfaces presented to client
filesystems and network protocol stacks.
</para>
<para>
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 (for example several
filesystems can have a function called <function>read()</function>, so long as they are
static). The system is also structured to eliminate the need for
dynamic memory allocation.
</para>
<para>
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.
</para>
<para>
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.
</para>
</chapter>
<!-- }}} -->
<!-- {{{ File System Table -->
<chapter id="fileio-fstab">
<title>File System Table</title>
<para>
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
<literal>FSTAB_ENTRY()</literal> macro.
</para>
<note>
<title>Note</title>
<para>
At present we do not support dynamic addition or removal of table
entries. However, an API similar to <function>mount()</function> would
allow new entries to be added to the table.
</para>
</note>
<para>
The table entries are described by the following structure:
</para>
<programlisting>
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 );
};
</programlisting>
<para>
The <structfield>name</structfield> field points to a string that
identifies this filesystem implementation. Typical values might be
"romfs", "msdos", "ext2" etc.
</para>
<para>
The <structfield>data</structfield> field contains any private data
that the filesystem needs, perhaps the root of its data structures.
</para>
<para>
The <structfield>syncmode</structfield> field contains a description of
the locking protocol to be used when accessing this filesystem. It
will be described in more detail in <xref linkend="fileio-synchronization">.
</para>
<para>
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:
</para>
<para>
The <function>opendir()</function> function pointer opens a directory
for reading. See <xref linkend="fileio-directories"> for details.
</para>
<para>
The <function>getinfo()</function> and
<function>setinfo()</function> function pointers provide support for
various minor control and information functions such as
<function>pathconf()</function> and <function>access()</function>.
</para>
<para>
With the exception of the <function>mount()</function> and
<function>umount()</function> 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.
</para>
</chapter>
<!-- }}} -->
<!-- {{{ Mount Table -->
<chapter id="fileio-mount-table">
<title>Mount Table</title>
<para>
The mount table records the filesystems that are actually active.
These can be seen as being analogous to mount points in Unix systems.
</para>
<para>
There are two sources of mount table entries. Filesystems (or other
components) may export static entries to the table using the
<literal>MTAB_ENTRY()</literal> macro. Alternatively, new entries may
be installed at run time using the <function>mount()</function>
function. Both types of entry may be unmounted with the
<function>umount()</function> function.
</para>
<para>
A mount table entry has the following structure:
</para>
<programlisting>
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
};
</programlisting>
<para>
The <structfield>name</structfield> field identifies the mount
point. This is used to direct rooted filenames (filenames that
begin with "/") to the correct filesystem. When a file
name that begins with "/" is submitted, it is matched
against the <structfield>name</structfield> 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 <structfield>root</structfield> field as the directory
pointer.
</para>
<para>
For example, consider a mount table that contains the following
entries:
</para>
<programlisting>
{ "/", "msdos", "/dev/hd0", ... }
{ "/fd", "msdos", "/dev/fd0", ... }
{ "/rom", "romfs", "", ... }
{ "/tmp", "ramfs", "", ... }
{ "/dev", "devfs", "", ... }
</programlisting>
<para>
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.
</para>
<para>
Unrooted file names (those that do not begin with a '/') are passed
straight to the filesystem that contains the current directory. The
current directory is represented by a pair consisting of a mount table
entry and a directory pointer.
</para>
<para>
The <structfield>fsname</structfield> field points to a string that
should match the <structfield>name</structfield> field of the
implementing filesystem. During initialization the mount table is
scanned and the <structfield>fsname</structfield> 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 <structfield>fs</structfield> pointer installed.
</para>
<para>
The <structfield>devname</structfield> 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.
</para>
<para>
The <structfield>data</structfield> field is a private data value. This
may be installed either statically when the table entry is defined, or
may be installed during the <function>mount()</function> operation.
</para>
<para>
The <structfield>valid</structfield> field indicates whether this mount
point has actually been mounted successfully. Entries with a false
<structfield>valid</structfield> field are ignored when searching for a
name match.
</para>
<para>
The <structfield>fs</structfield> field is installed after a successful
<function>mount()</function> operation to point to the implementing
filesystem.
</para>
<para>
The <structfield>root</structfield> field contains a directory pointer
value that the filesystem can interpret as the root of its directory
tree. This is passed as the <parameter>dir</parameter> argument of
filesystem functions that operate on rooted filenames. This field must
be initialized by the filesystem's <function>mount()</function>
function.
</para>
</chapter>
<!-- }}} -->
<!-- {{{ File Table -->
<chapter id="fileio-file-table">
<title>File Table</title>
<para>
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.
</para>
<para>
A file table entry has the following structure:
</para>
<programlisting>
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 */
};
</programlisting>
<para>
The <structfield>f_flag</structfield> field contains some FILEIO
control bits and some bits propagated from the
<parameter>flags</parameter> argument of the
<function>open()</function> call (defined by
<literal>CYG_FILE_MODE_MASK</literal>).
</para>
<para>
The <structfield>f_ucount</structfield> 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. It is also
incremented around each I/O operation to ensure that the file cannot
be closed while it has current I/O operations.
</para>
<para>
The <structfield>f_type</structfield> field indicates the type of the
underlying file object. Some of the possible values here are
<literal>CYG_FILE_TYPE_FILE</literal>,
<literal>CYG_FILE_TYPE_SOCKET</literal> or <literal>CYG_FILE_TYPE_DEVICE</literal>.
</para>
<para>
The <structfield>f_syncmode</structfield> field is copied from the
<structfield>syncmode</structfield> field of the implementing
filesystem. Its use is described in <xref linkend="fileio-synchronization">.
</para>
<para>
The <structfield>f_offset</structfield> field records the current file
position. It is the responsibility of the file operation functions to
keep this field up to date.
</para>
<para>
The <structfield>f_data</structfield> 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.
</para>
<para>
The <structfield>f_xops</structfield> 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.
</para>
<para>
The <structfield>f_mte</structfield> 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.
</para>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -