Linux——基础I/O2-操作系统如何访问文件|文件描述符的分配规则|重定向|如何理解一切皆文件

简介: 笔记

操作系统如何访问文件


文件可按照打开状态分为,被进程打开的文件(内存文件)和未打开文件


被进程打开的文件被加载到了内存,没打开的文件在磁盘上


操作系统要管理打开的文件,管理方式:先描述,再组织。操作系统用struct file进行管理文件,里面包含了文件的所有内容,包含属性,但文件的属性又来自哪?由于文件没有被打开时在磁盘上,文件=内容+属性,struct file里文件的属性就来源于磁盘。


进程和文件通过指针数组来进行维护,文件描述符的本质是数组下标

1.png2.png

task_struct中包含一个结构体指针,指针指向已打开的文件信息


2.pngfiles_struct结构体,该结构体有很多内容,其中有一个fd_array指针数组,数组默认大小为32或64


3.png


struct file里面有很多文件属性

4.png

操作系统是这样来访问文件的,fd_array也可以称为文件映射表/文件描述符表

5.png



文件描述符本质:数组下标


当用fopen打开文件时,底层调用open,open打开后会得到一个文件描述符,文件描述符被封装成FILE ,以FILE*的方式返回给fopen供用户去使用。


当用户开始fwrite的时候,传进来了一个FILE*(fopen的时候获得FILE*,fopen调用open获得fd,把fd放到FILE*里面),FILE*里面包含fd,并且FILE*里面封装了write,调用write之后就进入到了操作系统内部,然后自己执行了操作系统内部的write方法,执行write方法之后就找到了进程的task_struct,找到task_struct之后就找到了指针,然后找到files_struct,然后找到了fd_array[],这个数组再配合刚才传进来的fd,就找到了struct_file


文件描述符的分配规则


Linux进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0, 标准输出1, 标准错误。

0,1,2对应的物理设备一般是:键盘,显示器,显示器。


而现在知道,文件描述符就是从0开始的小整数。当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述目标文件。


于是就有了file结构体。表示一个已经打开的文件对象。而进程执行open系统调用,所以必须让进程和文件关联起来。


每个进程都有一个指针*files, 指向一张表files_struct,该表最重要的部分就是包涵一个指针数

组,每个元素都是一个指向打开文件的指针!所以,本质上,文件描述符就是该数组的标。


所以,只要拿着文件描述符,就可以找到对应的文件



我们关掉0

6.png

此时fd是07.png




修改一下,close(0)改为close(2)


8.png


我们可以看到此时fd是2,这是因为fd的分配规则是:fd会找到最小的,没有被占用的文件描述符。


此时我们把1关掉

9.png



此时不打印,此时fd一定是1,没打印这是因为1是标准输出流。标准输出流是往显示器打印,我们此时关掉了1,所以不往显示器打印了

10.png

注释掉关闭文件

11.png



注释掉后,内容打印到了log.txt中,这是因为打印的时候printf默认往stdout打(因为1里被stdout占领),stdout是file结构体,这个结构体里fileno默认为1,我们关闭了1,fd便去占领了1,这个fd是打开了log.txt的返回值,也就是1此时对应的是log.txt,printf只认1,而1此时被log.txt占领,所以打印到了log.txt,这种现象叫做输出重定向。常见的重定向有:>, >>, <

12.png

printf和fprintf这些应该都往显示器打印(标准输出),关闭1之后,打印到了log.txt中,这是因为1此时被log.txt占领。

13.png

14.png15.png

当系统启动时,系统会默认打开三个文件,Linux一切皆文件键盘,显示器,显示器,系统会给这三个创建struct file对象,这三个文件分别是键盘,显示器,显示器。把这三个对象的地址填入0(标准输入流),1(标准输出流),2(标准错误流)所对应的指针数组中。在语言层面我们只在下标为1的地址里打印,如果1(默认为显示器)被改为了文件,我们则会把数据打印在文件中。0也是如此如果把0所在下标的内容改为其它文件地址,标准输入流此时就是这个文件,直接获取文件内容


重定向的本质其实是,在操作系统内,更改fd对应的内容指向

16.png

从指定的流 stream 读取一行,并把它存储在 buffer所指向的字符串内


此时我们输入什么,它打印什么

17.png



只读

18.png19.png

稍作修改 ,此时关闭了0,给log.txt分配了0,也就是说log.txt此时成了标准输入流

20.png

fgets从log.txt获取了字符串,这就叫输入重定向

21.png



重定向


man dup2,把oldfd拷贝给newfd,拷贝的不是fd这个数字,而是指针数组里面的内容

22.png23.png

此时如果要输出重定向,就是把myfile的地址放到下标为1的格子,此时应该


dup(3,1)

24.png

此时直接打印10086

25.png

.

26.png

输出重定向

27.png

把下标为fd的元素内容(log.txt的地址),拷贝给下标为1的元素

38.png

追加重定向,删掉O_TRUNC(清空)加上O_APPEND即可

29.png30.png


此时没有close(fd)

41.png42.png

添加close(fd),此时却什么都没打印,这是因为有缓冲区存在

43.png


44.png


dup2具有刷新缓冲区的操作

45.png


46.png



如何理解一切皆文件

Linux的设计哲学,体现在软件设计层上,Linux是用C语言写的。


用C语言实现面向对象,让结构体里面包含成员方法,使用函数指针,底层不同的文件,对应着不同的操作方法,下面这些设备都是外设,所以每一个设备的核心访问函数,都可以是read,write(这俩个代表I/O),所有的设备都可以有自己的read和write,但是,代码的实现,一定是不一样的,这种方式下硬件没有任何的差别,看待所有的文件的方式都统一成了struct file

47.png48.png

相关文章
|
7月前
|
监控 Linux
Linux命令大全:echo与tail实现输出重定向。
这样,我们实现了使用echo和tail命令进行输出重定向的目的。在实际应用中,输出重定向技巧可节省时间,提高工作效率。希望本文内容对您了解和掌握Linux系统中echo与tail命令以及输出重定向的操作有所帮助。
245 27
|
7月前
|
Linux
【Linux】 Linux文件I/O常见操作技巧
以上就是Linux文件I/O操作的一些技巧,接纳它们,让它们成为你在Linux世界中的得力伙伴,工作会变得轻松许多。不过记住,技巧的运用也需要根据实际情况灵活掌握,毕竟,最适合的才是最好的。
239 28
|
10月前
|
存储 网络协议 Linux
【Linux】进程IO|系统调用|open|write|文件描述符fd|封装|理解一切皆文件
本文详细介绍了Linux中的进程IO与系统调用,包括 `open`、`write`、`read`和 `close`函数及其用法,解释了文件描述符(fd)的概念,并深入探讨了Linux中的“一切皆文件”思想。这种设计极大地简化了系统编程,使得处理不同类型的IO设备变得更加一致和简单。通过本文的学习,您应该能够更好地理解和应用Linux中的进程IO操作,提高系统编程的效率和能力。
460 34
|
9月前
|
存储 人工智能 运维
阿里云操作系统控制台——解决服务器磁盘I/O故障
阿里云操作系统控制台——解决服务器磁盘I/O故障
441 12
|
Python
文件元数据获取方法对比:`os.path` 与 `os.stat`
本文对比了Python中两种获取文件元数据的方法:`os.path`和`os.stat`。通过示例代码展示了如何获取文件大小和修改时间,并从性能、功能性和代码可读性三方面进行了详细对比。最终给出了根据具体需求选择合适方法的最佳实践建议。
240 2
|
图形学 开发者 存储
超越基础教程:深度拆解Unity地形编辑器的每一个隐藏角落,让你的游戏世界既浩瀚无垠又细节满满——从新手到高手的全面技巧升级秘籍
【8月更文挑战第31天】Unity地形编辑器是游戏开发中的重要工具,可快速创建复杂多变的游戏环境。本文通过比较不同地形编辑技术,详细介绍如何利用其功能构建广阔且精细的游戏世界,并提供具体示例代码,展示从基础地形绘制到植被与纹理添加的全过程。通过学习这些技巧,开发者能显著提升游戏画面质量和玩家体验。
934 3
|
存储 Unix Linux
Linux I/O 重定向与管道
【8月更文挑战第17天】重定向在Linux中改变命令I/O流向,默认有&quot;&gt;&quot;覆盖输出至文件及&quot;&gt;&gt;&quot;追加输出至文件末尾,便于保存结果;使用&quot;&lt;&quot;从文件读取输入而非键盘,高效处理数据。文件描述符如0(stdin)、1(stdout)、2(stderr)标识I/O资源,支持读写操作。管道以&quot;|&quot;连接命令,使前一命令输出成为后一命令输入,如排序用户或找出CPU占用最高的进程,构建复杂数据处理流程。
211 9
|
Unix Linux
linux中在进程之间传递文件描述符的实现方式
linux中在进程之间传递文件描述符的实现方式
|
监控 Linux
在Linux中,如何监控磁盘I/O性能?
在Linux中,如何监控磁盘I/O性能?