一、理解文件
再Linux下,IO设备全都被抽象成了文件,所以,一切的IO操作都变成了对文件的IO操作。
文件的补充知识
1.0kb的文件是占磁盘空间的。
2.文件=文件属性+文件内容。
3.所有的文件操作都是文件属性操作或文件内容操作。
4.我们打开文件,本质上是把磁盘级的文件加载到内存中,因为对磁盘的读写效率过低,所以要加载到内存中方便读写。
二、系统文件IO
我们打开文件,其实有很多方式,其中也有系统调用的方式。

其中:
pathname:要打开的文件名
flags:是一个位图,可以通过系统提供的宏来构成参数选项:
- O_RONLY:只读打开
- O_WRONLY:只写打开
- O_RDWR:读写打开
- O_CREAT:若文件不存在则创建它,使用mode表示创建文件的权限
- O_APPEND:追加写
返回值:若成功,则返回新打开的文件描述符,失败则返回-1。
那么什么是文件描述符呢?
二、文件描述符
文件描述符是一个整数,可以将其理解为数组下标,数组存储着这个进程打开的所有文件的地址。
我们如果尝试以后就会发现,打开文件后,它的文件描述符是3,那0,1,2呢?
其实,Linux进程在默认情况下会打开三个文件描述符,它们分别是标准输入0,标准输出1,标准错误2。它们分别对应的是:键盘、显示器、显示器。
文件描述符分配规则
存储文件描述符,也就是文件指针的数据结构,被称为files_struct,在这个数组中,找到一个最小的没有被使用的下标,作为新的文件描述符。
重定向
既然文件可以被关闭,那012是不是也可以呢?关闭了会怎么样?
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main() {
close(1);
int fd = open("output.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
printf("Hello World!\n");
close(fd);
return 0;
}
结果hello world却被输入到了output.txt,而显示器上什么也没有,这就是重定向。
在命令行也有常用的重定向操作,通常使用<,>>,>。

那么,系统有没有提供相关的系统调用呢?答案当然是有的。

其中,oldfd表示要打开的文件,newfd表示要关闭的文件。
如果调用成功,则返回newfd。失败返回-1。
三、一切皆文件
除了磁盘文件,其他的一些东西,也被Linux抽象成了文件,例如进程、磁盘、显示器、网卡、键盘等。这样做有什么好处呢?
对这些硬件设备进行操作,其实也可以抽象成读和写,和文件是一样的,所以,将他们抽象成为文件,就可以减少学习的成本。
操作系统为了管理一切被打开的文件,必然要先描述,再组织。而描述文件的数据结构叫做struct file 其中存储了文件的文件标识、引用计数、文件的打开模式、文件的权限、文件的位置和一个file_operations结构体,这个结构体里全是函数指针,包含了此文件的所有操作方法。
而未来,对于不同的硬件设备,只要驱动开发写好底层的回调函数,上层就可以调用统一的接口进行IO操作。

三、缓冲区
什么是缓冲区
缓冲区是内存的一块空间,用于暂时存储输入和输出的数据。
为什么需要缓冲区
本质上和为什么需要内存是一样的,由于对外设的读写过慢,所以先将数据存入缓冲区,之后一并进行IO,减少IO次数,提高效率。
缓冲类型
- 全缓冲区:这种缓冲方式要求填满整个缓冲区后才进行1/0系统调用操作。对于磁盘文件的操作通常使用全缓冲的方式访问。
- 行缓冲区:在行缓冲情况下,当在输入和输出中遇到换行符时,标准1/0库函数将会执行系统调用操作。当所操作的流涉及一个终端时(例如标准输入和标准输出),使用行缓冲方式。因为标准I/O库每行的缓冲区长度是固定的,所以只要填满了缓冲区,即使还没有遇到换行符,也会执行I/O系统调用操作,默认行缓冲区的大小为1024。
- 无缓冲区:无缓冲区是指标准1/0库不对字符进行缓存,直接调用系统调用。标准出错流stderr通常是不带缓冲区的,这使得出错信息能够尽快地显示出来。
除了默认的刷新,还有以下几种情况会导致缓冲区刷新:
1.缓冲区满了
2.执行flush
3.进程结束
在Linux中,库函数自带缓冲区,而系统调用没有缓冲区,说明缓冲区其实是由库函数实现的,由C标准库提供。
732

被折叠的 条评论
为什么被折叠?



