【Linux】基础IO

目录

理解"文件"

C文件操作接口特点

系统文件I/O

理解"一切皆文件"

缓冲区


理解"文件"

1、狭义理解:文件在磁盘里

2、广义理解:Linux下一切皆文件,键盘、显示器等等都是文件

3、系统理解:

(1)多个进程可能打开多个文件,文件也需要被管理,即:先描述,再组织。

(2)进程打开文件,进程是内核的数据结构,而文件其实也是内核的数据结构,最终其实就是两个内核数据结构之间的交互

(3)对⽂件的操作本质是进程对⽂件的操作

(4)磁盘的管理者是操作系统

(5)⽂件的读写本质不是通过C语⾔/C++的库函数来操作的(这些库函数只是为⽤户提供⽅便),⽽ 是通过⽂件相关的系统调⽤接⼝来实现的

4、文件类型:内存级(被打开);磁盘级

C文件操作接口特点

1、以w打开文件。不写只读后,文件内容会被清空

2、以a方式打开,不会清空文件内容,追加写入

系统文件I/O

引入1:打开⽂件的⽅式不仅仅是fopen,ifstream等流式,语⾔层的⽅案,其实系统才是打开⽂件最底层的⽅案。不过,在学习系统⽂件IO之前,先要了解下如何给函数传递标志位,该⽅法在系统⽂件IO接⼝中 会使⽤到:

1、函数传递标志位:

引入2、3:采⽤系统接⼝来 进⾏⽂件访问,下面直接以系统代码的形式

2、open函数

参数一:文件的路径;

参数二:标志位

参数三:文件的权限

下面是open的一个实例:拿着fd就能用write去往fd里面写东西

返回值:成功-返回新打开的文件描述符(fd);失败-返回-1

下面实例是打开的普通文件,但是只有3、4、5、6,并没有0、1、2

但是C语言中有stdin stdout stderr,那么FILE其实是一个结构体,我们可以猜测FILE里面一定封装了文件描述符fd

所以不管是C语音,C++,Python等等语言,其实都会封装fd,上层有各种各样的cin、cout、cerror等等,底层都是文件描述符fd去实现的。

程序员写代码用的C语言,语言层做了封装,消除了底层不同操作系统平台的差异 (不同操作系统的系统调用接口不一样 的),也就是能提供统一的接口,增加了代码的可移植性

比如有10个平台,就有10分完整一样的代码,底层接口不一样,但是上层就是统一的封装接口。

3、write函数:

(1)格式化的输入输出,文本写入/二进制写入都是语言层面的工具,底层其实调用的都是write这个函数,write不关心具体是以什么方式写入的,文本也行,二进制也行

下面是一个写入示例:

4、文件描述符fd

(1)⽂件描述符就是⼀个⼩整数

下面是一个进程访问自己对应的文件的过程,是通过文件描述符去查找当前进程有哪些文件的,因为每个进程都有自己打开的文件,注意,不管是对文件内容进行增删查改,首先都是把文件读到内存中,因为CPU没办法直接访问磁盘。本质上,⽂件 描述符就是该数组的下标。

(2)⽂件描述符的分配规则

cpp 复制代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
	close(0);
	//close(2);
	int fd = open("myfile", O_RDONLY);
	if (fd < 0) {
		perror("open");
		return 1;
	}
	printf("fd: %d\n", fd);
	close(fd);
	return 0;
}

发现是结果是: fd: 0 或者 fd 2,关闭0,分配给新的文件的描述符就是0,;关闭2,分配给新的文件的描述符就是2 。在files_struct数组当中,找到当前没有被使用最小的⼀个下标,作为新的⽂件描述符。

(3)重定向+dup2

重定向:把file_struct中的1小标的内容换成3小标的内容,利用dup2(fd,1),其中fd=3去实现。最终本来应该打印到显示器的内容,就会打印到log.txt中去,但其实本质是1的地址存的是3的地址了,上层只关注1,不关注存的地址是哪个文件的,所以导致看起来把内容打印到log.txt里面去了。

因此输入、输出重定向,本质是:打开文件的方式+dup2

输入重定向:dup2(fd,0),本来应该从0的内容指向的文件读,但是现在0存的是fd的内容,也就是从log.txt里面去读了,fd把0的内容覆盖了;本来应该从键盘读,现在从别的文件读。

输出重定向:dup2(fd,1),1的地址是log.txtx文件的地址,应该输出到1显示器的内容,但其实是把1已经是log.txt的地址了,最终输出到log.txt中去了;本来应该写到显示器,现在写到别的文件了。

上面其实都是把本应该写入0/1的内容写到fd指向的文件里面去了,也就是重定向,只是0是用户写入的,所以是输入重定向;1是用户应该读的,但是现在只能从og.txt里面去读了。

重定向完整的写法: ls -a -l 1>log.txt 但是一般会省略1

(4)Q1:eg. ls -a -l > log.txt 子进程去执行ls -a -l,进行程序替换。进程替换,会影响重定向的结果吗?进程替换后,会不会影响我曾经打开的文件?

A1:毫不影响!!因为进程替换只是会替换代码和数据,文件那一部分不影响。

也就是说,程序替换之前,先做重定向,然后子进程执行,就可以在子进程内部从指定的文件进行输入输出了。

(5)Q2:一个文件可以被多个进程打开,要是A进程执行close(fd),文件就被关了,那B进程怎么访问呢?也就是close(fd)到底执行了什么?

A2:如果还有其他进程打开该文件 :仅减少该文件的 "引用计数 ",不关闭底层资源(直到所有进程都 close 后,内核才彻底释放资源)

(6)Q3:重定向后,标准输出1在文件log.txt里,标准错误2还在显示器上,因为只是拿3的内容覆盖1了,所以本应该输出到显示器1的内容输出到3log.txt里面,但是标准错误2也是显示器文件的地址,所以2还是指向显示器文件。

./a.out 1>log.normal 2>log.error

(7)进程和文件之间是通过files_struct去关联的,二者的管理是解耦的,进程有自己的管理,文件也有自己的管理。

(8)每个文件也有文件内存缓冲区的指针,通过file找到文件的缓冲区

(9)磁盘级文件,属性放inode里,内容放内核文件缓冲区里

理解"一切皆文件"

1、通过软件层屏蔽底层差异,实际上就是多态,通过files_struct中的read、write函数去实现,具体某个设备都有自己的读写方法,也就是同一接口,不同的实现。

用虚拟文件系统

缓冲区

1、为什么要引入缓冲区?

提高效率

2、C语言标准库也有缓冲区,一般用printf把内容先写到C语言的缓冲区,然后用write写到OS内部的缓冲区,或者用fflush刷新到OS内部的缓冲区,如下图所示

3、FILE是C语言的一个struct,里面封装了fd、缓冲区

对下面这个代码的解释:

(1)没有write,有close(fd)时,打印log.txt文件啥都没有,就是因为4行printf全部写到C语言的缓冲区了,但缓冲区中的数据还没来得及写入文件,就被提前关闭了close(fd)。

(2)有write,有没有close(fd)无所谓,打印log.txt都有内容,因为write是系统调用,直接写到OS内核文件缓冲区了。

4、为啥(printf)C语言缓冲区->(write)OS文件内核缓冲区->磁盘硬件,为啥C语言还有个缓冲区,不能直接printf从OS文件内核缓冲区->磁盘硬件?

因为直接输出到文件内核缓冲区其实是多次系统调用,先存到C语言的缓冲区里面,可以大大减少系统调用,降低成本,所以C语言提供的缓冲区一次比较大,后面一次性就把所有缓冲区的内容一次性刷新到内核缓冲区里面去了。也就是实际上可能调用10次printf,1次write

5、例子

6、补充:数据库

对数据库的增删查改其实就是进程把数据从内存写到磁盘上,也就是"持久化""落盘"。

相关推荐
FL16238631295 分钟前
win11+WSL+Ubuntu-xrdp+远程桌面闪退+黑屏闪退解决
linux·运维·ubuntu
石头53013 分钟前
Kubernetes监控全栈解决方案:从零搭建Prometheus+Grafana监控体系
linux
ha204289419419 分钟前
Linux操作系统学习记录之---TcpSocket
linux·网络·c++·学习
AOwhisky1 小时前
Linux逻辑卷管理:从“固定隔间”到“弹性存储池”的智慧
linux·运维·服务器
C Yu小白2 小时前
Linux系统调用与文件操作详解
linux·运维·服务器
ZFB00012 小时前
【麒麟桌面系统】V10-SP1 2503 系统知识——常见用户组简介
linux·运维·kylin
EndingCoder3 小时前
类的继承和多态
linux·运维·前端·javascript·ubuntu·typescript
ZFB00013 小时前
【麒麟桌面系统】V10-SP1 2503 系统知识——添加用户
linux·运维·kylin
ZFB00014 小时前
【麒麟桌面系统】V10-SP1 2503 系统知识——进入救援模式
linux·运维·kylin
RisunJan4 小时前
Linux命令-iptables-restore命令(从文件批量恢复 iptables 防火墙规则)
linux·运维·网络