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

📄 fileio.sgml

📁 eCos操作系统源码
💻 SGML
📖 第 1 页 / 共 3 页
字号:
<para>This table is analogous to a combination of the filesystem and mounttables.</para><para>The <structfield>valid</structfield> field is set<literal>true</literal> if the stack's <function>init()</function>function returned successfully and the<structfield>syncmode</structfield> field contains the<literal>CYG_SYNCMODE_SOCK_*</literal> bits described above.</para><!----><para>The <structfield>name</structfield> field contains the name of theprotocol stack.</para><!----><para>The <structfield>devname</structfield> field names the device that the stack is using. This mayreference a device under &quot;/dev&quot;, or may be a name that is onlymeaningful to the stack itself.</para><!----><para>The <function>init()</function> function pointer is called duringsystem initialization to start the protocol stack running. If itreturns non-zero the <structfield>valid</structfield> field is setfalse and the stack will be ignored subsequently.</para><para>The <function>socket()</function> function is called to attempt to create a socket in thestack. When the <function>socket()</function> API function is called the netstack table isscanned and for each valid entry the <function>socket()</function>function pointer is called. Ifthis returns non-zero then the scan continues to the next valid stack,or terminates with an error if the end of the table is reached.</para><para>The result of a successful socket call is an initialized file objectwith the <structfield>f_xops</structfield> field pointing to thefollowing structure:</para><programlisting width=72>struct cyg_sock_ops{    int (*bind)      ( cyg_file *fp, const sockaddr *sa, socklen_t len );    int (*connect)   ( cyg_file *fp, const sockaddr *sa, socklen_t len );    int (*accept)    ( cyg_file *fp, cyg_file *new_fp,                       struct sockaddr *name, socklen_t *anamelen );    int (*listen)    ( cyg_file *fp, int len );    int (*getname)   ( cyg_file *fp, sockaddr *sa, socklen_t *len, int peer );    int (*shutdown)  ( cyg_file *fp, int flags );    int (*getsockopt)( cyg_file *fp, int level, int optname,                       void *optval, socklen_t *optlen);    int (*setsockopt)( cyg_file *fp, int level, int optname,                       const void *optval, socklen_t optlen);    int (*sendmsg)   ( cyg_file *fp, const struct msghdr *m,                       int flags, ssize_t *retsize );    int (*recvmsg)   ( cyg_file *fp, struct msghdr *m,                       socklen_t *namelen, ssize_t *retsize );};</programlisting><para>It should be obvious from the names of these functions which API callsthey provide support for. The <function>getname()</function> functionpointer provides support for both <function>getsockname()</function>and <function>getpeername()</function> while the<function>sendmsg()</function> and <function>recvmsg()</function>function pointers provide support for <function>send()</function>,<function>sendto()</function>, <function>sendmsg()</function>,<function>recv()</function>, <function>recvfrom()</function> and<function>recvmsg()</function> as appropriate.</para></chapter><!-- }}} --><!-- {{{ Select --><chapter id="fileio-select"><title>Select</title><para>The infrastructure provides support for implementing a selectmechanism. This is modeled on the mechanism in the BSD kernel, but hasbeen modified to make it implementation independent.</para><para>The main part of the mechanism is the <function>select()</function>API call. This processes its arguments and calls the<function>fo_select()</function> function pointer on all file objectsreferenced by the file descriptor sets passed to it. If the samedescriptor appears in more than one descriptor set, the<function>fo_select()</function> function will be called separatelyfor each appearance.</para><para>The <parameter>which</parameter> argument of the<function>fo_select()</function> function will either be<literal>CYG_FREAD</literal> to test for read conditions,<literal>CYG_FWRITE</literal> to test for write conditions or zero totest for exceptions. For each of these options the function shouldtest whether the condition is satisfied and if so return true. If itis not satisfied then it should call<function>cyg_selrecord()</function> with the<parameter>info</parameter> argument that was passed to the functionand a pointer to a <structname>cyg_selinfo</structname> structure.</para><para>The <structname>cyg_selinfo</structname> structure is used to record information about currentselect operations. Any object that needs to support select mustcontain an instance of this structure.  Separate <structname>cyg_selinfo</structname>structures should be kept for each of the options that the object canselect on - read, write or exception.</para><para>If none of the file objects report that the select condition issatisfied, then the <function>select()</function> API function putsthe calling thread to sleep waiting either for a condition to becomesatisfied, or for the optional timeout to expire.</para><para>A selectable object must have some asynchronous activity that maycause a select condition to become true - either via interrupts or theactivities of other threads. Whenever a selectable condition issatisfied, the object should call <function>cyg_selwakeup()</function> with a pointer tothe appropriate <structname>cyg_selinfo</structname> structure. If the thread is still waiting,this will cause it to wake up and repeat its poll of the filedescriptors. This time around, the object that caused the wakeupshould indicate that the select condition is satisfied, and the<function>select()</function> API call will return.</para><para>Note that <function>select()</function> does not exhibit real timebehaviour: the iterative poll of the descriptors, and the wakeupmechanism mitigate against this. If real time response to device orsocket I/O is required then separate threads should be devoted to eachdevice of interest and should use blocking calls to wait for acondition to become ready.</para></chapter><!-- }}} --><!-- {{{ Devices --><chapter id="fileio-devices"><title>Devices</title><para>Devices are accessed by means of a pseudo-filesystem, &quot;devfs&quot;, that ismounted on &quot;/dev&quot;. Open operations are translated into calls to<function>cyg_io_lookup()</function> and if successful result in a file object whose<structfield>f_ops</structfield> functions translate filesystem API functions into calls intothe device API.</para></chapter><!-- }}} --><!-- {{{ Writing a New Filesystem --><chapter id="fileio-writing"><title>Writing a New Filesystem</title><para>To create a new filesystem it is necessary to define the fstab entryand the file IO operations. The easiest way to do this is to copy anexisting filesystem: either the test filesystem in the FILEIO package,or the RAM or ROM filesystem packages.</para><para>To make this clearer, the following is a brief tour of the FILEIOrelevant parts of the RAM filesystem.</para><para>First, it is necessary to provide forward definitions of the functionsthat constitute the filesystem interface:</para><programlisting width=72>//==========================================================================// Forward definitions// Filesystem operationsstatic 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 operationsstatic 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 operationsstatic 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 );</programlisting><para>We define all of the fstab entries and all of the file IOoperations. We also define alternatives for the<structfield>fo_read</structfield> and<structfield>fo_lseek</structfield> file IO operations.</para><para>We can now define the filesystem table entry. There is a macro,<literal>FSTAB_ENTRY</literal> to do this:</para><programlisting width=72>//==========================================================================// 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);</programlisting><para>The first argument to this macro gives the fstab entry a name, theremainder are initializers for the field of the structure.</para><para>We must also define the file operations table that is installed in allopen file table entries:</para><programlisting width=72>// -------------------------------------------------------------------------// 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};</programlisting><para>These all point to functions supplied by the filesystem except the<structfield>fo_select</structfield> field which is filled with apointer to <function>cyg_fileio_seltrue()</function>. This is providedby the FILEIO package and is a select function that always returnstrue to all operations.</para><para>Finally, we need to define a set of file operations for use whenreading directories. This table only defines the<structfield>fo_read</structfield> and<structfield>fo_lseek</structfield> operations. The rest are filledwith stub functions supplied by the FILEIO package that just return anerror code.</para><programlisting width=72>// -------------------------------------------------------------------------// 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};</programlisting><para>If the filesystem wants to have an instance automatically mounted onsystem startup, it must also define a mount table entry. This is donewith the <literal>MTAB_ENTRY</literal> macro. This is an example fromthe test filesystem of how this is used:</para><programlisting width=72>MTAB_ENTRY( testfs_mte1,                   "/",                   "testfs",                   "",                   0);</programlisting><para>The first argument provides a name for the table entry. The followingarguments provide initialization for the<structfield>name</structfield>, <structfield>fsname</structfield>,<structfield>devname</structfield> and <structfield>data</structfield>fields respectively.</para><para>These definitions are adequate to let the new filesystem interactwith the FILEIO package. The new filesystem now needs to be fleshedout with implementations of the functions defined above. Obviously,the exact form this takes will depend on what the filesystem isintended to do. Take a look at the RAM and ROM filesystems forexamples of how this has been done.</para></chapter><!-- }}} --></part>

⌨️ 快捷键说明

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