2008年(13)
分类: C/C++
2008-10-30 21:43:53
文件I/O操作
通常文件作为一种最常用的资源,到处需要它。文件是建立在文件系统上的一层概念,有什么的文件系统,就有什么样的文件,所以谈论文件时离不开文件系统。但不管是什么文件系统,操作系统统一制定一套接口,这也是POSIX一方面。
首先对于操作系统来说,在用户模式只有文件描述符才能操纵文件。文件描述符是一个无符号的整数,应该可以用unsigned int 来定义,最大值是OPEN_MAX,最小当然是0.三个常用的描述符在
文件操作
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
__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
//为XPG定义所有可用符号
#ifdef __USE_XOPEN
# include
#endif
#ifdef __USE_MISC
# ifndef R_OK /* Verbatim from
/* 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 /*
# 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
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 */