eCos Reference Manual
Prev |  | Next

# Chapter 22. 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 bits propagated from the `flags` argument of 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. It is also incremented around each I/O operation to ensure that the file cannot be closed while it has current I/O operations.

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 Chapter 24.

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 pointers, like their counterparts in the filesystem structure, implement minor control and info functions such as `fpathconf()`.

The second argument to the `fo_read()` and `fo_write()` function pointers 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 infrastructure, any changes to it must be made with the appropriate logical operations.

Prev | Home | Next
Mount Table | Up | Directories