Chinaunix首页 | 论坛 | 博客
  • 博客访问: 55671
  • 博文数量: 13
  • 博客积分: 850
  • 博客等级: 准尉
  • 技术积分: 220
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-10 16:20
文章存档

2008年(13)

我的朋友
最近访客

分类: C/C++

2008-10-30 21:43:53

文件I/O操作
     通常文件作为一种最常用的资源,到处需要它。文件是建立在文件系统上的一层概念,有什么的文件系统,就有什么样的文件,所以谈论文件时离不开文件系统。但不管是什么文件系统,操作系统统一制定一套接口,这也是POSIX一方面。
     首先对于操作系统来说,在用户模式只有文件描述符才能操纵文件。文件描述符是一个无符号的整数,应该可以用unsigned int 来定义,最大值是OPEN_MAX,最小当然是0.三个常用的描述符在里定义:STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO.

 

     文件操作

     open函数,可以打开或创建一个文件。其实create函数是从open里改造过来,完全可以用open代替。对于这点和windows刚好相反,windows里一般用createfile打开和创建文件,很少直接用openfile打开文件。
     不知道为什么?open函数在里定义,原本的意思是文件控制,一般什么有关锁机制定义在这个文件里.
     int open(const char *pathname,int oflag,...);
     可以看出它将文件描述符用int表示可能返回负数,出错.另外后面的...表明可以省略mode,标准只规定前两个.一般是:
     int open(const char* pathname,int oflag,mode_t mode);
     mode 是指S_IRWXU,S_IRUSR,S_IWUSR等,当oflag带有O_CREAT时才用.

     creat函数,原型: int creat(const char* pathname,mode_t mode);  等价于 open(pathname,O_WRONLY | O_CREAT | O_TRUNC,mode);
     这里注意,creat并不是create,没有字母e.O_WRONLY | O_CREAT | O_TRUNC表示 读写|创建|清除所有内容,这时返回值也是int型,返回-1表示出错.

     close函数.它定义在里,原型:
     int close(int filedes);      返回-1表示出错.
    
     lseek函数.他的作用就是对已经打开的文件定位的.原型:
     off_t lseek(int filedes,off_t offset,int whence);  同样出错返回-1,同时将error设置成ESPIPE;
     我的理解参数: offset 精确小偏移调整, whence表示大的偏移方向 SEEK_SET(文件头)  SEEK_CUR(文件当前指针)  SEEK_END(文件末尾);

     read函数.明显就是从一个文件里读一些数据.这也是文件的作用和意义的体现.定义在
     ssize_t read(int filedes,void * buf,size_t nbytes);   同样,出错返回-1.成功返回实际读到buf的字节数.若是到了文件末尾返回0.
     其实POSIX.1经典定义是 int read(int fieldes,char * buf,unsigned nbytes);
     对比可以看出,只改变缓冲区指针类型 char * 改变为 void *,这原于各自的解释不同. 另外 ssize_t 表示有符号整数,也就是int.size_t 表示无符号整数,unsigned.
    

     write函数.定义在,原型:
     ssize_t write(int filedes,const void *buf,size_t nbytes);   成功返回已经写入字节数,出错返回-1;
    
    
     可以看出以上的read和write函数是不带缓冲区的.根本就没有设置缓冲类型.效率不高.
     另外XSI标准扩展了两个函数,可以说是两个原子函数,因为他把读写和定位放到一起.
     #include
     ssize_t pread(int filedes,void *buf,size_t nbytes,off_t offset);        成功返回读到的字节数,出错返回-1,若是到了文件末尾返回0.
     ssize_t pwrite(int filedes,const void *buf,size_t nbytes,off_t offset); 成功返回读到的字节数,出错返回-1.  


     dup和dup2函数.复制和创建一个文件描述符.
     很显然,它并不创建文件,只是创建一个文件描述符函数.
     原型:  int dup(int filedes);                     参数都调用者给出一个参考值(要复制的值),返回下一个最小的可用文件描述符.
            int dup2(int filedes,int filedes2);       第二参数为调用者指定要下个复制的文件描述符,其他和dup一样.返回值一定大于或等于最后一个参数值.
   
     fd_return =  dup(fd)   =    fcntl(fd,F_DUPFD,0);   //返回值大于等于0,返回的fd_return和fd共享同一个文件项(dentry).但各一套描述符标志.
     fd_return  =  dup2(fd1,fd2)  =   {close(fd2);//此时关闭肯定最小  fdcntl(fd1,F_DUPFD,fd2);}//其他的同上
                                                    


    sync,fsync和fdatasync函数.将缓存数据写到磁盘上,保持磁盘数据和缓存一致.
    int fsync(int filedes);        //更新缓存
    int fdatasync(int filedes);    //将文件的数据从缓存里更新到最新版本,不更新文件属性.      上面两个成功返回0,出错返回-1.
    void sync(viod);               //将所有缓冲区写到磁盘里.其实也有这样一个shell命令.

 

    fcntl函数,文件控制函数.这个函数应该是文件操作最为复杂的一个函数.原型:
    int fcntl(int filedes,int cmd,.../* int arg */);               //出错返回-1,成功根据cmd而定.
    cmd定义如下:
    1.复制现有描述符(F_DUPFD). 
    2.获得/设置文件描述符标记(F_GETFD或F_SETFD). //返回文件描述符标志(FD_CLOSEXEC)
    3.获得/设置文件状态标志(F_GETFL或F_SETFL).   //获得和设置文件本身标志,也就是oflag(O_RDONLY,O_WRONLY,O_RDWR,O_SYNC,O_NONBLOCK等等.)
    4.获得/设置异步I/O所有权(F_GETOWN或F_SETOWN). //
    5.获得/设置记录锁(F_GETLK或F_SETLK或F_SETLKW). //待补中...
   

    ioctl函数.它的作用是补充上面所有函数的不足.一般上面的不能的I/O操作可以请ioctl帮忙.原型:
    int ioctl(int filedes,int request,...);                 //出错返回-1,成功根据request而定.


以上基本上是unix所有的基本文件操作函数(全部是系统调用).下一章将讲述高级文件操作.另外,对于文件系统目录,/dev/fd/n下的文件打开时,等效复制了文件描述符n,因为n一开机的时候全部都已经打开.
 


以下是fcntl.h文件.
/*
 * POSIX Standard: 6.5 File Control Operations 
 */

#ifndef _FCNTL_H
#define _FCNTL_H 1

#include

/* This must be early so can define types winningly.  */
__BEGIN_DECLS

/* Get the definitions of O_*, F_*, FD_*: all the
   numbers and flag bits for `open', `fcntl', et al.  */
//获取一些flag标志定义,等等.
#include                     

/* For XPG all symbols from should also be available.  */
//为XPG定义所有可用符号

#ifdef __USE_XOPEN
# include       
#endif

#ifdef __USE_MISC
# ifndef R_OK   /* Verbatim from .  Ugh.  */
/* Values for the second argument to access.
   These may be OR'd together.  */  //一些访问权限标志.可以用OR一起使用.
#  define R_OK 4  /* Test for read permission.  */
#  define W_OK 2  /* Test for write permission.  */
#  define X_OK 1  /* Test for execute permission.  */
#  define F_OK 0  /* Test for existence.  */
# endif
#endif /* Use misc.  */

/* XPG wants the following symbols.  */     //XPG定义下列符号
#ifdef __USE_XOPEN  /* has the same definitions.  */
# define SEEK_SET 0 /* Seek from beginning of file.  */
# define SEEK_CUR 1 /* Seek from current position.  */
# define SEEK_END 2 /* Seek from end of file.  */
#endif /* XPG */

#ifdef __USE_ATFILE
# define AT_FDCWD  -100 /* Special value used to indicate
        the *at functions should use the
        current working directory. */
# define AT_SYMLINK_NOFOLLOW 0x100 /* Do not follow symbolic links.  */
# define AT_REMOVEDIR  0x200 /* Remove directory instead of
        unlinking file.  */
# define AT_SYMLINK_FOLLOW 0x400 /* Follow symbolic links.  */
# define AT_EACCESS  0x200 /* Test access permitted for
        effective IDs, not real IDs.  */
#endif

/* Do the file control operation described by CMD on FD.
   The remaining arguments are interpreted depending on CMD.

   This function is a cancellation point and therefore not marked with
   __THROW.  */  
extern int fcntl (int __fd, int __cmd, ...);        //fcntl原型

/* Open FILE and return a new file descriptor for it, or -1 on error.        
   OFLAG determines the type of access used.  If O_CREAT is on OFLAG,
   the third argument is taken as a `mode_t', the mode of the created file.
//打开文件并返回一个新的文件描述符,出错返回-1.当OFLAG含有O_CREAT时,第三个参数才能被用上,也就是创建文件时.
  
   This function is a cancellation point and therefore not marked with
   __THROW.  */
#ifndef __USE_FILE_OFFSET64
extern int open (__const char *__file, int __oflag, ...) __nonnull ((1));      //这是open的原始定义
#else
# ifdef __REDIRECT
extern int __REDIRECT (open, (__const char *__file, int __oflag, ...), open64)
     __nonnull ((1));
# else
#  define open open64
# endif
#endif
#ifdef __USE_LARGEFILE64
extern int open64 (__const char *__file, int __oflag, ...) __nonnull ((1));
#endif

 

#ifdef __USE_ATFILE
/* Similar to `open' but a relative path name is interpreted relative to
   the directory for which FD is a descriptor.

   NOTE: some other `openat' implementation support additional functionality
   through this interface, especially using the O_XATTR flag.  This is not
   yet supported here.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
# ifndef __USE_FILE_OFFSET64
extern int openat (int __fd, __const char *__file, int __oflag, ...)
     __nonnull ((2));
# else
#  ifdef __REDIRECT
extern int __REDIRECT (openat, (int __fd, __const char *__file, int __oflag,
    ...), openat64) __nonnull ((2));
#  else
#   define openat openat64
#  endif
# endif

extern int openat64 (int __fd, __const char *__file, int __oflag, ...)
     __nonnull ((2));
#endif

/* Create and open FILE, with mode MODE.  This takes an `int' MODE
   argument because that is what `mode_t' will be widened to.

   This function is a cancellation point and therefore not marked with
   __THROW.  */
#ifndef __USE_FILE_OFFSET64
extern int creat (__const char *__file, __mode_t __mode) __nonnull ((1));    //这里是creat原型
#else
# ifdef __REDIRECT
extern int __REDIRECT (creat, (__const char *__file, __mode_t __mode),
         creat64) __nonnull ((1));
# else
#  define creat creat64
# endif
#endif
#ifdef __USE_LARGEFILE64
extern int creat64 (__const char *__file, __mode_t __mode) __nonnull ((1));
#endif

#if !defined F_LOCK && (defined __USE_MISC || (defined __USE_XOPEN_EXTENDED \
            && !defined __USE_POSIX))
/* NOTE: These declarations also appear in ; be sure to keep both
   files consistent.  Some systems have them there and some here, and some
   software depends on the macros being defined without including both.  */

/* `lockf' is a simpler interface to the locking facilities of `fcntl'.
   LEN is always relative to the current file position.
   The CMD argument is one of the following.  */

# define F_ULOCK 0 /* Unlock a previously locked region.  */
# define F_LOCK  1 /* Lock a region for exclusive use.  */
# define F_TLOCK 2 /* Test and lock a region for exclusive use.  */
# define F_TEST  3 /* Test a region for other processes locks.  */

# ifndef __USE_FILE_OFFSET64
extern int lockf (int __fd, int __cmd, __off_t __len);
# else
# ifdef __REDIRECT
extern int __REDIRECT (lockf, (int __fd, int __cmd, __off64_t __len), lockf64);
# else
#  define lockf lockf64
# endif
# endif
# ifdef __USE_LARGEFILE64
extern int lockf64 (int __fd, int __cmd, __off64_t __len);
# endif
#endif

#ifdef __USE_XOPEN2K
/* Advice the system about the expected behaviour of the application with
   respect to the file associated with FD.  */
# ifndef __USE_FILE_OFFSET64
extern int posix_fadvise (int __fd, __off_t __offset, __off_t __len,
     int __advise) __THROW;
# else
# ifdef __REDIRECT_NTH
extern int __REDIRECT_NTH (posix_fadvise, (int __fd, __off64_t __offset,
        __off64_t __len, int __advise),
      posix_fadvise64);
# else
#  define posix_fadvise posix_fadvise64
# endif
# endif
# ifdef __USE_LARGEFILE64
extern int posix_fadvise64 (int __fd, __off64_t __offset, __off64_t __len,
       int __advise) __THROW;
# endif


/* Reserve storage for the data of the file associated with FD.

   This function is a possible cancellation points and therefore not
   marked with __THROW.  */
# ifndef __USE_FILE_OFFSET64
extern int posix_fallocate (int __fd, __off_t __offset, __off_t __len);
# else
# ifdef __REDIRECT
extern int __REDIRECT (posix_fallocate, (int __fd, __off64_t __offset,
      __off64_t __len),
         posix_fallocate64);
# else
#  define posix_fallocate posix_fallocate64
# endif
# endif
# ifdef __USE_LARGEFILE64
extern int posix_fallocate64 (int __fd, __off64_t __offset, __off64_t __len);
# endif
#endif


/* Define some inlines helping to catch common problems.  */
#if __USE_FORTIFY_LEVEL > 0 && defined __extern_always_inline \
    && defined __va_arg_pack_len
# include
#endif

__END_DECLS

#endif /* fcntl.h  */


     
    

 

阅读(1302) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~