本博文设计的IO不属于ANSI C的文件IO,所涉及的每一个函数都是一个系统调用。主要涉及POSIX.1的不带缓存的IO操作的基础部分。
1.文件描述符
在linux内核中,对于一个文件的描述只需要一个标示符即可。而不是一个复杂的指针,仅仅是一个int型的整数,有文件描述符可以直接通过系统API直接操作内核资源,换句话说,下面的所有操作API都会产生一个系统调用。这样说来,int的大小就限制了操作系统可以打开的最大文件数。但是文件打开上限主要受OPEN_MAX限制
这个文件的概念是linux内核的文件概念,它包括文件目录里面的具体文件,sock,管道,串口等一系列可以看做文件操作的集合
其中常用的文件描述符0,1,2分别表示STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO。在文件<unistd.h>中定义
2.open函数
这是一个打开文件的函数
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open(const char *filename, int flags, /*, mode_t mode */);
其中flag是文件状态标记,由下面参数或运算构成(定义在fcntl.h):
O_RDONLY
O_WRONLY
O_RDWR
O_APPEND
O_CREAT:只有有这一个参数的时候open函数才需要调用第三个参数,指明权限
O_EXCL:如果文件存在,则出错
O_TRUNC:如果文件存在则截断为0
O_NOCTTY
O_NONBLOCK:非阻塞,
O_SYNC:每次write都等物理成功写入
成功返回文件描述符,否则返回负数
3 create函数
有了open函数就不太需要create函数了。因为可以由O_REAT创建文件。
#include <sys/types.h>
#include <sys/stat.h>
#include <stat.h>
int create(const char *filename, mode_t mode);
出错返回-1
4 close函数
这是一耳光关闭文件的函数
#include <unistd.h> int close(int fd);出错返回-1
关闭一个打开的文件。同时释放该文件的所有记录锁
需要说明的是,当进程退出时,会隐式的关闭本进程打开的文件
5 lseek函数
lseek函数可以定位文件当前的操作位置。一般打开的文件如果没有指定O_APPEND,那么文件的操作位置是开头
#include <sys/types.h> #include <unistd.h> off_t lseek(int fd, off_t offset, int whence); 出错返回-1,成功返回新的偏移量。
对于offset的解释与最后一个参数whence(何处)有关:
SEEK_SET,从开始位置计算,offset不能为负数
SEEK_CUR,从当前位置计算,offset可以为正为负
SEEK_END,从最后位置计算,offset可以为正为负
SEEK_SET,从开始位置计算,offset不能为负数
SEEK_CUR,从当前位置计算,offset可以为正为负
SEEK_END,从最后位置计算,offset可以为正为负
注意:文件偏移量是每个进程独有的,不同的进程打开同一个文件,但是可以有不同的文件偏移量。
6 read函数
从文件中读取数据
#include <unistd.h> ssize_t read(int fd, void *buffer, size_t nBytes);成功返回读取到的字节数,不一定等于nBytes,出错返回-1,到达文件尾返回0
7 write函数
向文件中写入数据
#include <unistd.h> ssize_t write(int fa, void *buffer, size_t nbytes); 成功返回已经写入的字节数,出错返回-1
8 dup函数和dup2函数
这两个函数可以用来复制一个文件描述符(file description)
#include <unistd.h> int dup(int fd); int dup2(int fd1, int fd2); 成功返回新的文件描述符,出错返回-1这两个函数的区别是:
dup复制fd返回一个可用的最小文件描述符;
dup2用文件描述符fd2来复制fd1,如果fd2已经打开,那么先将其关闭。
复制之后的文件描述符共享文件表项,表现为拥有一样文件状态标记和文件偏移量
9 fcntl函数
这个函数可以改变已经打开的文件的性质
#include <sys/types.h> #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd /*,int arg*/); 成功依赖cmd,出错返回-1fcntl有五种功能
- 复制一个现存的描述符(cmd=F_DUPFD )
- 获取/设置一个文件状态标记(cmd=F_GETFD/F_SETFD)
- 获取/设置文件状态标记(cmd=F_GETFL/F_SETFL)
- 获取/设置异步IO所有权(cmd=F_GETOWN/F_SETOWN)
- 获取/设置记录锁(cmd=F_GETLK,F_SETLK,F_SETLKW)
10 ioctl函数
这个不是很熟悉,略