一、文件描述符
对于内核而言所有打开的文件都是通过文件描述符引用。文件描述符是一个非负整数。当打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。当读或者写一个文件时使用open或creat返回文件描述符标识该文件,将作为参数传递给read或write
UNIX系统shell把文件描述符0与进程的标准输入关联,文件描述符1与标准输出关联,文件描述符2与标准错误关联。这是各种shell以及很多程序使用的惯例,与UNIX内核无关。
在符合POSIX.1的应用程序中。幻数0、1、2以及被标准化。但是建议使用符号常量:STDIN_FILENO、STDOUT_FILENO 、STDERR_FILENO以提高可读性。这些常量定义在头文件<unistd.h>中。
文件描述符的变化范围是0~OPEN_MAX-1。早期可以同时使用的文件描述符是20个(既可以同时打开20个文件),现在多是64。可以使用函数sysconf来查看OPEN_MAX的值。
long sysconf(int _SC_OPEN_MAX)
二、文件操作
1、文件创建与打开
(1)open
1)函数原型
#include <fcntl.h>
int open(const char*path,int oflag,.../*mode_t mode*/);
2)参数说明
path是要打开或创建文件的名字。
最后一个参数写为...表明余下的参数的数量及类型是可变的。仅当创建新文件时才使用最后这个参数mode.用于指定文件的访问权限位。
oflag参数可以用来说明此函数的多个选项。用下列一个或多个常量进行“或”运算构成oflag参数
O_RDONLY
O_WRONLY
O_RDWR
O_EXEC 只执行打开
O_SEARCH 只搜索打开(应用与目录)
打开/创建文件时,至少得使用上述五个常量中的一个。以下常量是选用的:
O_APPEND
O_CREAT
O_EXCL
O_TRUNC
O_NOCTTY
O_NONBLOCK
以下三个常量同样是选用的,它们用于同步输入输出
O_DSYNC
O_RSYNC
O_SYNC
3)返回值
open 函数返回的文件描述符一定是最小的未用的描述符值。
(2)openat
int openat(int fd, const char* path,int oflag,.../*mode_t mode*/);
与open 不同的是openat函数可以使用相对路径名打开目录中的文件,而不再只打开当前工作目录。
path参数是绝对路径名时,fd参数被忽略,openat函数就相当于open函数;path参数是相对路径名时,fd参数指出了相对路径名在文件系统中的开始地址。fd参数是通过打开相对路径名所在的目录来获取;若fd参数的值为AT_FDCWD则,路径名会在当前工作目录中获取。
(3)creat
#include<fcntl.h>
int create(const char* path,mode_tmode);
等价于
open(path,O_WRONLY | O_CREAT | O_TRUNC, mode);
create 的不足之处是它一只写的方式打开所创建的文件。
2、文件关闭
#include<unistd.h>
int close(int fd);
关闭一个文件时还会释放该进程加在该文件上的所有记录锁。
当一个进程结束时,内核会自动关闭它所有打开的文件。
3、读文件
(1)read
1)函数原型
#include<unistd.h>
ssize_t read(int fd,void *buf,size_t nbytes)
2)返回值
read 成功时,返回读到的字节数。如已到达文件的尾端,则返回0;若出错,返回-1。
3)说明
多种情况会使实际读到的字节数少于要求读的字节数。例如:在读到要求的字节数之前已经到达了文件的尾端;从终端设备读时,通常一次最多读一会等
4、写文件
(1)write
#include <unistd.h>
ssize_t write(int fd,const void* buf,size_t nbytes);
write函数向打开的文件写数据。若成功返回已写的字节数,若出错返回-1.
5、其它
(1)使用int dup(int fd)或int dup2(int fd,int fd2)函数进行文件描述符复制
(2) 使用int fsync(int fd)或void sync(void);将缓冲区数据写至磁盘
(3)使用fcntl函数gaibian已经打开的文件属性
(4)使用off_t lseek(int fd,off_t offset,int whence);函数显示设置一个已经打开文件的偏移量
三、与标准C函数库的区别
标准C库是对系统文件I/O接口的封装。标准I/O库处理了很多细节,如缓冲区分配、以优化的块长度执行I/O等。
1、不带缓冲
不带缓冲指:每个read和write都调用内核中的一个系统调用
2、文件描述符与流
对于内核所有的文件操作都是围绕文件描述符来进行的;但是标准C I/O库是围绕流(FILE*)进行的。