文件操作相关函数介绍及使用
1.open/close函数
-
需包含的头文件:
#include <unistd.h> #include <fcntl.h>
-
open:
int open(const char* pathname, int flags); int open(const char* pathname, int flags, mode_t mode);
-
常用参数
flags:O_RDONLY 只读、O_WRONLY 只写、O_RDWR 读写、O_APPEND 添加、O_CREAT 创建、O_EXCL 存在、O_TRUNC 清零、O_NONBLOCK 非阻塞
mode:用数字表示文件的权限,如0744(第一个0代表八进制),仅用于O_CREAT
-
返回值
成功:返回打开文件所对应的文件描述符(整数)
失败:-1,设置errno
-
-
close:
int close(int fd);
-
返回值
成功:返回0
失败:-1,设置errno
-
2.错误处理函数
-
strerror
char* strerror(int errnum); //函数原型
-
使用方法
printf("xxx error: %s\n", strerror(errno)); //函数用法
-
返回值:错误的字符串描述
-
-
perror
void perror(const char* s);
-
使用方法
perror("open error");
-
3.read/write函数
-
需包含的头文件:
#include <unistd.h> #include <fcntl.h>
-
read:
ssize_t read(int fd, void* buf, size_t count);
-
参数
fd:文件描述符
buf:存数据的缓冲区
count:缓冲区大小
-
返回值
成功:读到的字节数
失败:-1,设置errno
特殊:-1,并且errno = EAGIN或者EWOULDBLOCK,说明正在read以非阻塞方式读一个设备文件(网络文件),并且文件无数据。
-
-
write
ssize_t write(int fd, const void* buf, size_t count);
-
参数
fd:文件描述符
buf:待写入数据的缓冲区
count:数据大小
-
返回值
成功:写入的字节数
失败:-1,设置errno
-
4.文件描述符表
-
PCB进程控制块:本质为结构体
-
成员:文件描述符表
-
文件描述符:0/1/2/3……/1023(原则上会优先使用现有最小的文件描述符)
-
已经占用的文件描述符:
0-STDIN_FILENO
1-STDOUT_FILENO
2-STDERR_FILENO
-
5.fcntl函数
可以用于查询文件的属性信息和设置文件属性信息
int flags = fcntl(STDIN_FILENO, F_GETFL); //获取文件的属性信息
flags |= O_NONBLOCK; //加上属性
int ret = fcntl(STDIN_FILENO, F_SETFL, flags); //设置文件属性
- F_GETFL:获取文件属性
- F_SETFL:设置文件属性
6.lseek函数
off_t lseek(int fd, off_t offset, int whence);
-
参数:
fd:文件描述符
offset:偏移量
whence:其实偏移位置:SEEK_SET/SEEK_CUR/SEEK_END
-
返回值:
成功:较起始位置的偏移量
失败:-1,设置errno
-
应用场景:
1、文件的“读”、“写”使用同一个偏移位置。
2、使用lseek获取文件大小。
int len = lseek(fd, 0, SEEK_END);
3、使用lseek拓展文件大小,要想使文件大小真正扩展,必须引起IO操作。
int len = lseek(fd, 111, SEEK_END); write(fd, "\0", 1);
-
可以使用truncate函数直接拓展文件
int ret = truncate("文件名", 250);
-
7.传入传出参数
-
传入参数
- 指针作为函数参数
- 通常有const关键字修饰
- 指针指向有效区域,在函数内部做读操作
char* strcpy(char* dest, const char* src); //第二个参数为传入参数
-
传出参数
- 指针作为函数参数
- 在函数调用之前,指针指向的空间可以无意义,但是必须有效
- 在函数内部做写操作
- 函数调用结束后,充当函数返回值
char* strcpy(char* dest, const char* src); //第一个参数为传出参数
-
传入传出参数
- 指针作为函数参数
- 在函数调用前,指针指向的空间有实际意义
- 在函数内部,先做读操作,后做写操作
- 函数调用结束后,充当函数返回值
8.硬链接原理
- 示意图
- dentry会随着硬链接的建立而创建,但是inode是独一无二的