-
对于内核而言,所有打开的文件都通过文件描述符引用,文件描述符是一个非负整数
文件描述符 标准 符号常量 文件描述符0 标准输入 STDIN_FILENO 文件描述符1 标准输出 STDOUT_FILENO 文件描述符2 标准错误 STDERR_FILENO -
函数open和openat---打开文件
int open(const char *path, int oflag, .../*mode_t mode*/) int openat(int fd,const char *path, int oflag, .../*mode_t mode*/) 两函数的返回值:若成功,返回文件描述符,若出错,返回-1
- path---要打开或创建文件的名字
- oflag---用来说明此函数的多个选项
- fd---把open和openat函数区分开,有下列三种情况
- path参数指定的是绝对路径名,在这种情况下,fd参数被忽略,openat函数相当于open
- path参数指定的是相对路径名,fd参数指出了相对路径名在文件系统中的开始地址。fd参数是通过打开相对路径名所在的目录来获取
- path参数指定的是相对路径名,fd参数具有特殊值AT_FDCWD。在这种情况下,路径名在当前工作目录中获取,openat函数在操作上和open函数相似
-
函数creat---创建文件
int creat(const char *path, mode_t mode) 返回值:若成功,返回为只写打开的文件描述符。若出错,返回-1
-
函数close---关闭文件
int close(int fd) 返回值:若成功,返回0。若出错,返回-1
- 关闭一个文件时会释放该进程加在改文件上的所有记录锁
-
函数lseek---显示地为一个打开文件设置偏移量
off_t lseek(int fd, off_t offset, int whence) 返回值:若成功,返回新的文件偏移量。若出错,返回-1
对参数offset的解释和参数whence的值有关
- 若whence = SEEK_SET,则将该文件的偏移量设置为距文件开始处offset个字节
- 若whence = SEEK_CUR,则将该文件的偏移量设置为其当前值加offset,offset可正可负
- 若whence = SEEK_END,则将该文件的偏移量设置为文件长度加offset,offset可正可负
-
函数read---读数据
ssize_t read(int fd, void *buf,size_t nbytes) 返回值:读到的字节数,若已到文件尾,返回0。若出错,返回-1
- 有多种情况可使实际读到的字节数少于要求读的字节数
-
函数write---写数据
ssize_t write(int fd, const void *buf,size_t nbytes) 返回值:若成功,返回已写的字节数。若出错,返回-1
单个进程打开文件时内核数据结构图
- 两个独立进程各自打开了同一个文件,有如下关系图
多个进程读取同一文件都能正常工作。每个进程都有它自己的文件表项,其中也有它自己的当前文件偏移量。但是,当多个进程写同一个文件时,则可能产生预想不到的结果
原子操作指的是由多步组成的一个操作,如果原子操作被执行,要么执行完所有步骤,要么一步也不执行,不可能执行所有步骤中的一个子集
-
函数dup和dup2---复制一个现有的文件描述符
int dup(int fd) int dup2(int fd,int fd2); 返回值:若成功,返回新的文件描述符。若出错,返回-1
- fd---将要复制的文件描述符
- fd2---指定新描述符的值(将要返回的)
- dup返回的新文件描述符一定是当前可用文件描述符中的最小数值
- dup2是一个原子操作,
close(fd2); fcntl(fd,F_DUPFD,fd2);
-
函数fcntl---改变打开已经打开的文件的属性
int fcntl(int fd, int cmd, .../* int arg */) 返回值:若成功,则依赖于cmd。若出错,返回-1
- fcntl有以下5中功能
- 复制一个已有的描述符(cmd = F_DUPFD 或 F_DUPFD_CLOEXEC)
- 获取/设置文件描述符标志(cmd = F_GETFD 或 F_SETFD)
- 获取/设置文件状态标志(cmd = F_GETFL 或 F_SETFL)
- 获取/设置异步I/O所有权(cmd = F_GETOWN 或 F_SETOWN)
- 获取/设置记录锁(cmd = F_GETLK、F_SETLK 或 F_SETLKW)
- 在修改文件描述符标志或文件状态标志时必须谨慎,先要获得现在的标志值,然后按照期望修改,最后设置新标志值。不能只执行F_SETFD或F_SETFL命令,这样会关闭以前设置的标志位
- fcntl有以下5中功能