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

📄 ramfs.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 5 页
字号:
//==========================================================================
//
//      ramfs.c
//
//      RAM file system
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s):           nickg
// Contributors:        nickg
// Date:                2000-07-25
// Purpose:             RAM file system
// Description:         This is a RAM filesystem for eCos. It attempts to
//                      provide full POSIX-compatible filesystem behaviour
//                      while at the same time being efficient in terms of
//                      time and space used.
//                      
//
//####DESCRIPTIONEND####
//
//==========================================================================
// 
// General Description
// ===================
// 
// This is an implementation of a RAM filesystem for eCos. Its goal is
// to provide a working example of a filesystem that provides most of
// the required POSIX functionality. And obviously it may also be
// useful in its own right.
//
//
// Nodes
// -----
//
// All files and directories are represented by node objects. Each
// ramfs_node structure contains the following fields:
//
// mode   - Node type, file or directory.
// refcnt - Number of references to this node. For files each open counts as
//          a reference and for directories a node is referenced when it is made
//          current directory, or is opened for reading.
// nlink  - Number of links to this node. Each directory entry that references
//          this node is a link. 
// size   - Size of the data in this node in bytes.
// atime  - Last time this node was accessed.
// mtime  - Last time the data in this node was modified.
// ctime  - Last time the status information in this node was changed.
//
// The data storage in a node is controlled by the configuration and
// can take two forms. These will be described later.
//          
// Directories
// -----------
//
// A directory is a node whose data is a list of directory entries. To
// simplify management of these, long directory entries are split into
// a chain of fixed size ramfs_dirent structures. These contain the
// following fields:
//
// node    - Pointer to node referenced by this entry. This is present in
//           every directory entry fragment
// inuse   - Set to 1 if this entry is in use, zero if it is free.
// first   - Set to 1 if this is the first fragment of a directory entry.
// last    - Set to 1 if this is the last fragment of a directory entry.
// namelen - The size of the whole file name.
// fraglen - The number of bytes of the file name that are stored in this
//           fragment.
// next    - The offset of the next fragment of this directory entry.
// name    - The characters of the fragment of the file name stored in this
//           entry.
//
// Small file names are stored in a single fragment. Longer names are
// stored in a chain of fragments.
//
// Data Storage
// ------------
//
// Two data storage mechanisms may be configured, the SIMPLE and the
// BLOCKS mechanisms.
//
// SIMPLE Data Storage
// ~~~~~~~~~~~~~~~~~~~
//
// This mechanism simply uses malloc() and free() to allocate the
// memory for both nodes and file data. File data is stored in a
// single malloced vector that is realloced as necessary to acquire
// more space. 
//
// The advantage of this approach is that the RAM filesystem only uses
// as much memory as it needs, the rest is available for use by other
// components. It also requires much simpler data structures and code
// in the filesystem to manage. However, if any files get to be a
// significant proportion of the size of the heap, there is the danger
// that fragmentation will prevent any further extension of some
// files, even if there is enough memory in total. It also requires an
// implementation of malloc() to be present. If this needs to be
// present for other components,then this is not a significant
// overhead, but including it just for use by this filesystem
// represents a major addition of code and data structures.
//
//
// BLOCKS Data Storage
// ~~~~~~~~~~~~~~~~~~~
//
// This mechanism divides the memory used for file storage into fixed
// sized blocks. These blocks may either be allocated using
// malloc()/free(), or may be obtained from a array of blocks reserved
// for the purpose. Configuration allows the block size to be
// selected, as well as the allocation mechanism, and in the case of a
// block array, whether it is defined here or by an external
// component.
// 
// Data storage in nodes is arranges in three arrays of pointers to
// blocks. The first array points directly to data blocks, the second
// to blocks which themselves contain pointers to data blocks, and the
// third to blocks which contain pointers to blocks which contain
// pointers to data blocks. In the default configuration These last
// two arrays have only one element each.
// 
// The following shows how the data is arranged in a fully populated
// file with a 256 byte block size using the default configuration.
// 
//      Node
// ~            ~
// |            |
// |            |
// +------------+
// |     *------+--------> data block 0
// +------------+
// |     *------+--------> data block 1
// +------------+
// |     *------+--------> data block 2
// +------------+
// |     *------+--------> data block 3
// +------------+
// |     *------+--------> data block 4
// +------------+
// |     *------+--------> data block 5
// +------------+
// |     *------+--------> data block 6
// +------------+
// |     *------+--------> data block 7
// +------------+
// |     *------+--------> +------------+
// +------------+          |     *------+--------> data block 8
// |     *------+----+     +------------+
// +------------+    |     |            |
//                   |     ~            ~
//                   |     |            |
//                   |     +------------+
//                   |     |     *------+--------> data block 71
//                   |     +------------+
//                   |     
//                   +---->+------------+         +------------+
//                         |     *------+-------->|     *------+---->data block 72
//                         +------------+         +------------+
//                         |            |         |            |
//                         ~            ~         ~            ~
//                         |            |         |            |
//                         +------------+         +------------+
//                         |     *------+---+     |     *------+----> data block 135
//                         +------------+   |     +------------+
//                                          |
//                                          |     +------------+
//                                          +---->|     *------+----> data block 4104
//                                                +------------+
//                                                |            |
//                                                ~            ~
//                                                |            |
//                                                +------------+
//                                                |     *------+----> data block 4167
//                                                +------------+
// 
// 
//
// The advantages of this approach are that, first, memory usage is
// divided into discreet fixed size blocks which are easier to
// manage. When using malloc() to allocate them, they will fit into
// any free memory of at least the right size. Using the block array
// option removes the need to have a malloc() implementation at all.
//
// The disadvantages of this mechanism are that, first, when using
// malloc() to allocate blocks, the per-block memory allocator
// overhead is paid for each block, rather than per file. This may
// result in less memory overall being available for data
// storage. When using the block array, it is permanently reserved for
// use by the ram filesystem, and is not available for use by other
// components.
//
//==========================================================================

#include <pkgconf/system.h>
#include <pkgconf/hal.h>
#include <pkgconf/kernel.h>
#include <pkgconf/io_fileio.h>
#include <pkgconf/fs_ram.h>

#include <cyg/kernel/ktypes.h>         // base kernel types
#include <cyg/infra/cyg_trac.h>        // tracing macros
#include <cyg/infra/cyg_ass.h>         // assertion macros

#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <dirent.h>

#include <stdlib.h>
#include <string.h>

#include <cyg/fileio/fileio.h>

#include <cyg/kernel/kapi.h>
#include <cyg/infra/diag.h>

//==========================================================================
// Sizes derived from configuration

// -------------------------------------------------------------------------
// Simple malloc based allocator parameters

#ifdef CYGPKG_FS_RAM_SIMPLE

#define RAMFS_FILESIZE_MAX      UINT_MAX

#else

// -------------------------------------------------------------------------
// Block allocator parameters

// The number of nodes per block
#define RAMFS_NODES_PER_BLOCK (CYGNUM_RAMFS_BLOCK_SIZE/sizeof(ramfs_node))

// The number of indirect pointers that can be stored in a single data block
#define RAMFS_INDIRECT_PER_BLOCK (CYGNUM_RAMFS_BLOCK_SIZE/sizeof(ramfs_block *))

// The number of directory entries that can be stored in a single data block
#define RAMFS_DIRENT_PER_BLOCK  (CYGNUM_RAMFS_BLOCK_SIZE/sizeof(ramfs_dirent))

// Number of bytes contained in a one level indirect block
#define RAMFS_INDIRECT1_BLOCK_EXTENT (RAMFS_INDIRECT_PER_BLOCK* \
                                      CYGNUM_RAMFS_BLOCK_SIZE)

// number of bytes contained in a two level indirect block
#define RAMFS_INDIRECT2_BLOCK_EXTENT (RAMFS_INDIRECT_PER_BLOCK* \
                                      RAMFS_INDIRECT_PER_BLOCK* \
                                      CYGNUM_RAMFS_BLOCK_SIZE)

// The maximum data offset for data directly accessed from the node
#define RAMFS_DIRECT_MAX        (CYGNUM_RAMFS_BLOCKS_DIRECT*CYGNUM_RAMFS_BLOCK_SIZE)

// The maximum data offset for data accessed from the single level indirect blocks
#define RAMFS_INDIRECT1_MAX     (RAMFS_DIRECT_MAX+                      \
                                 (CYGNUM_RAMFS_BLOCKS_INDIRECT1*        \
                                  RAMFS_INDIRECT1_BLOCK_EXTENT))

// The maximum data offset for data accessed from the two level indirect blocks
#define RAMFS_INDIRECT2_MAX     (RAMFS_INDIRECT1_MAX+                   \
                                 (CYGNUM_RAMFS_BLOCKS_INDIRECT2*        \
                                  RAMFS_INDIRECT2_BLOCK_EXTENT))

// The maximum size of a file
#define RAMFS_FILESIZE_MAX      RAMFS_INDIRECT2_MAX

#endif

//==========================================================================
// Forward definitions

// Filesystem operations
static int ramfs_mount    ( cyg_fstab_entry *fste, cyg_mtab_entry *mte );
static int ramfs_umount   ( cyg_mtab_entry *mte );
static int ramfs_open     ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
                             int mode,  cyg_file *fte );
static int ramfs_unlink   ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );
static int ramfs_mkdir    ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );
static int ramfs_rmdir    ( cyg_mtab_entry *mte, cyg_dir dir, const char *name );
static int ramfs_rename   ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
                             cyg_dir dir2, const char *name2 );
static int ramfs_link     ( cyg_mtab_entry *mte, cyg_dir dir1, const char *name1,
                             cyg_dir dir2, const char *name2, int type );
static int ramfs_opendir  ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
                             cyg_file *fte );
static int ramfs_chdir    ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
                             cyg_dir *dir_out );
static int ramfs_stat     ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
                             struct stat *buf);
static int ramfs_getinfo  ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
                             int key, void *buf, int len );
static int ramfs_setinfo  ( cyg_mtab_entry *mte, cyg_dir dir, const char *name,
                             int key, void *buf, int len );

// File operations
static int ramfs_fo_read      (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
static int ramfs_fo_write     (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
static int ramfs_fo_lseek     (struct CYG_FILE_TAG *fp, off_t *pos, int whence );
static int ramfs_fo_ioctl     (struct CYG_FILE_TAG *fp, CYG_ADDRWORD com,
                                CYG_ADDRWORD data);
static int ramfs_fo_fsync     (struct CYG_FILE_TAG *fp, int mode );        
static int ramfs_fo_close     (struct CYG_FILE_TAG *fp);
static int ramfs_fo_fstat     (struct CYG_FILE_TAG *fp, struct stat *buf );
static int ramfs_fo_getinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len );
static int ramfs_fo_setinfo   (struct CYG_FILE_TAG *fp, int key, void *buf, int len );

// Directory operations
static int ramfs_fo_dirread      (struct CYG_FILE_TAG *fp, struct CYG_UIO_TAG *uio);
static int ramfs_fo_dirlseek     (struct CYG_FILE_TAG *fp, off_t *pos, int whence );


//==========================================================================
// Filesystem table entries

// -------------------------------------------------------------------------
// Fstab entry.
// This defines the entry in the filesystem table.
// For simplicity we use _FILESYSTEM synchronization for all accesses since
// we should never block in any filesystem operations.

FSTAB_ENTRY( ramfs_fste, "ramfs", 0,
             CYG_SYNCMODE_FILE_FILESYSTEM|CYG_SYNCMODE_IO_FILESYSTEM,
             ramfs_mount,
             ramfs_umount,
             ramfs_open,
             ramfs_unlink,
             ramfs_mkdir,
             ramfs_rmdir,
             ramfs_rename,
             ramfs_link,
             ramfs_opendir,
             ramfs_chdir,
             ramfs_stat,
             ramfs_getinfo,
             ramfs_setinfo);

// -------------------------------------------------------------------------
// File operations.
// This set of file operations are used for normal open files.

static cyg_fileops ramfs_fileops =
{
    ramfs_fo_read,
    ramfs_fo_write,
    ramfs_fo_lseek,
    ramfs_fo_ioctl,
    cyg_fileio_seltrue,
    ramfs_fo_fsync,
    ramfs_fo_close,
    ramfs_fo_fstat,
    ramfs_fo_getinfo,
    ramfs_fo_setinfo
};

// -------------------------------------------------------------------------
// Directory file operations.
// This set of operations are used for open directories. Most entries
// point to error-returning stub functions. Only the read, lseek and
// close entries are functional.

static cyg_fileops ramfs_dirops =
{
    ramfs_fo_dirread,
    (cyg_fileop_write *)cyg_fileio_enosys,
    ramfs_fo_dirlseek,
    (cyg_fileop_ioctl *)cyg_fileio_enosys,
    cyg_fileio_seltrue,
    (cyg_fileop_fsync *)cyg_fileio_enosys,
    ramfs_fo_close,
    (cyg_fileop_fstat *)cyg_fileio_enosys,
    (cyg_fileop_getinfo *)cyg_fileio_enosys,
    (cyg_fileop_setinfo *)cyg_fileio_enosys
};

//==========================================================================
// Data typedefs
// Some forward typedefs for the main data structures.

struct ramfs_node;
typedef struct ramfs_node ramfs_node;

struct ramfs_dirent;
typedef struct ramfs_dirent ramfs_dirent;

#ifndef CYGPKG_FS_RAM_SIMPLE

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -