文件描述符
在linux中,文件IO的系统调用,是 以文件描述符,即一个非负整数,来指代打开的文件,你可以认为,操作文件描述符就是在操作文件
并且,对于每个进程而言,他们的文件描述符是自成一套的
以下截图是为了验证每个进程的文件描述符自成一套,我们可以看到有左边两个程序,t1.c和t2.c,他们几乎是一样的,不同的是打印的名称以及打开的文件不同,然后右边是他们执行的结果,可以看到他们打开的文件描述符是相同的
以下是标准描述符
标准描述符其实就和编程中的关键字类似,是系统已经提前定义好的,分别是标准输入,标准输出,标准错误,这三个是基本上shell启动时就会打开了,然后他们的值分别是0,1,2
打开的文件一般是有上限的,比如最多同时打开1024个文件,这样的话,文件描述符的取值就是0-1023,基于这一点,文件描述符的值一般是 最小的可用的,比如我们之前打开的文件描述符是3,因为0,1,2这三个已经被用了,所以3就是 最小的可用的值
这里我们可以再来实验下,比如我关掉标准错误,然后在打开一个文件,看看它的文件描述符是多少
我们可以看到,当我们关掉标准错误在打开一个文件时,这时候的文件描述符就是2了,因为打开前只有0和1在使用,所以2就是最小的可用的值
磁盘文件IO的系统调用(函数)
主要就是4个吧,我们可以通过man命令对这些系统调用进行查看,右边终端就是输入的命令,左边是呈现的结果,按q退出,例如下面这张图
-
open函数:打开一个文件,以 flags 的方式打开 pathname 文件,或者赋予创建文件 mode 的权限并以 flags 的方式打开它
函数声明 int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode);
参数介绍
- pathname: 这里就是打开文件的路径名
- flags: 这个是文件打开的标志,简单来说就是你要用什么方式打开这个文件,只读、只写、可读可写等等
- mode: 这个是创建文件的文件权限,就是如果说你要创建这个文件,你要给他什么权限
返回值:返回的就是文件描述符啦,一个整数
-
read函数:从指定文件中读取数据,从 fd 中一次最多读取 count 字节的数据到缓冲区 buf 中
函数声明 ssize_t read(int fd, void *buf, size_t count);
参数介绍:
- fd: 这个是要进行读取的文件的文件描述符
- buf: 这个是存储读取数据的地方
- count: 表示一次最大的读取数
返回值:返回的是读取的字节数(不一定和count相等)
需要注意的是,有时候我们可能想以字符串的方式打印读取的数据,这时候记得要给缓冲区buf最后加上一个 空字符\0 用以表示字符串的结束(虽然不加好像也问题)
-
write函数:向指定文件中写入数据,从缓冲区 buf 中向 fd 一次写入最多 count 字节的数据
函数声明 ssize_t write(int fd, const void *buf, size_t count);
参数介绍:
- fd: 这个是要进行写入的文件的文件描述符
- buf: 这个是存储写入数据的地方
- count: 表示一次最大的写入数
返回值:返回的是写入的字节数(不一定和count相等)
需要注意的是
对磁盘文件执行 I/O 操作时,write()调用成功并不能保证数据已经写入磁盘。因为为了减少磁盘活动量和加快 write()系统调用,内核会缓存磁盘的 I/O 操作
-
lseek函数:改变文件的偏移量,决定了文件IO的开始位置
函数声明 off_t lseek(int fd, off_t offset, int whence);
先说一下什么是文件偏移量,我们可以简单的理解为文件打开时光标的位置,这样我们读取或者写入都是从光标开始向文件后方进行,
参数介绍:
- fd: 这个是要进行操作的文件的文件描述符
- offset: 这个是要改变的偏移量大小,可正可负
- whence: 这个表示从文件的什么位置开始改变,以下是whence的值
返回值:返回的是从文件开头开始算起的文件偏移量
这里给一些lseek的例子,可以让你更好的理解
文件空洞
事实上,文件偏移量的改变是会改变文件的表面大小的,但不会影响磁盘上的大小
比如说,文件test.txt有三个字节的内容,现在你让他偏移100个字节,这个文件的表面大小就会增长到100字节,但磁盘上的大小还是三字节,这些增长的东西就是文件空洞了,文件空洞是不会占用磁盘空间的
以下是一个例子,左边是创建一个文件,然后刚开始是0字节,我们用一个函数先是把它的偏移量设置为10,然后写入abc三个字节的数字,这时候发现文件的大小是13字节,可是我们只写入了3字节的数据,然后打开文件,也就是右边的图,可以看到在abc,也就是我们实际写入的数据前,有一些文件空洞,这些就是文件偏移量造成的