文件描述符
文件描述符可以实现进程和打开文件之间的交互
引入头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
文件操作
打开文件
函数原型
int open(const char *pathname, int flags);
//文件名 打开方式
int open(const char *pathname, int flags, mode_t mode);
//文件名 打开方式 权限
返回值
执行成功时,open函数返回一个文件描述符,表示已经打开的文件;
执行失败时,open函数返回-1,并设置相应的errno
参数列表
flags和mode都是一组掩码的合成值
flags表示打开或创建的方式
flags可选项
掩码 | 含义 |
---|---|
O_RDONLY | 以只读的方式打开 |
O_WRONLY | 以只写的方式打开 |
O_RDWR | 以读写的方式打开 |
O_CREAT | 如果文件不存在,则创建文件 |
O_EXCL | 仅于O_CREAT连用,实现如果文件已存在,则open失败 |
O_TRUNC | 如果文件存在 |
O_APPEND | 以追加方式打开文件,每次调用write时,文件指针自动先移到文件尾,用于多进程写同一个文件的情况 |
O_NONBLOCK O_NDELAY | 对管道、设备文件和socket使用,以非阻塞方式打开文件,无论有无数据读取或等待,都会立即返回进程之中 |
O_SYNC | 同步打开文件,只有在数据被真正写入物理设备后才返回 |
O_ASYNC | 对管道、设备文件和socket使用,开启信号驱动IO。一旦可读或者可写发送信号 |
使用完文件,要调用close关闭文件描述符
mode 表示文件的访问权限
示例
int fd = open("file", O_RDWR | O_CREAT, 0755);//表示给755的权限
if(fd == -1)
{
perror("open failed!\n");
exit(-1);
}
创建文件
函数原型
int creat(const char *pathname, mode_t mode);
//文件名 权限
//creat现在已经不常用,它等价于
open(pathname, O_CREAT|O_TRUNC|O_WRONLY, mode);
文件关闭
使用完文件,要使用close来关闭文件。
函数说明
调用close后,该进程对文件所加的锁全都被释放,并且使文件的打开引用计数减1,只有文件的打开引用计数变为0以后,文件才会被真正地关闭。
函数原型
int close(int fd);
//fd表示文件描述符,是先前由open或creat创建文件时的返回值
不带缓冲的文件IO
使用read和write来读写文件,它们统称为不带缓冲的IO
read函数
函数原型
#include<unistd.h>
ssizr_t read(int fd, void *buf, size_t count);
//文件描述符 缓冲区 长度
返回值
出错返回-1
文件描述符读取完了,返回0
其他情况返回读写的个数
示例
#include <myfunc.h>
int main(int argc, char *argv[]) {
ARGS_CHECK(argc, 2);
int fd = open(argv[1], O_RDWR);
ERROR_CHECK(fd, -1, "open");
printf("fd = %d\n",fd);
char buf[128] = {0};
int ret = read(fd, buf, sizeof(buf));
printf("buf = %s, ret = %d\n", buf, ret);
close(fd);
return 0;
}
read的效率问题
使用不带缓冲IO的时候,CPU需要陷入内核态来处理文件读取。如果频繁地使用read来读取少量数据,数据的读取效率会比较低
使用read的场景
读取常规文件时,文件内容大于读取长度(即还没有遇到EOF,读取字符数达到count),此时返回值等于count(即最大读写字节数)
读取常规文件时,文件内容小于读取长度,此时返回值等于文件内容长度
读取网络文件的时候,由于数据传输不稳定,可能会导致文件还没有传输完成,read函数就已经返回的情况。此时返回值等于成功读取的字符数
write函数
函数原型
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
//文件描述符 缓冲区 长度
返回值
出错返回-1
文件描述符读取完了,返回0
其他情况返回读写的个数
示例
#include <myfunc.h>
int main(int argc, char *argv[]) {
ARGS_CHECK(argc, 2);
int fd = open(argv[1], O_RDWR);
ERROR_CHECK(fd, -1, "open");
printf("fd = %d\n", fd);
int ret = write(fd, &fd, sizeof(fd));
printf("ret = %d\n", ret);
close(fd);
return 0;
}