【戒焦戒躁,can win】Linux--IO文件描述符

回忆 C 语言文件操作

fopen

# include <stdio.h>
int main()
{
	// 第一个参数为文件名, 如果没有指定具体路径,就是在当前工作目录打开
	// 第二个参数是指定打开文件方式, w表示写方式打开文件
	FILE* fp fopen("whatever.txt", "w"); 
	
	// 打开文件失败
	if (fp == NULL) 
	{
		perror("fopen");
		return 1;
	}
	close(fp);
	return 0;
}

当程序运行时,程序变成进程,文件打开操作会由进程执行。因此,这样进程就跟文件产生了关联。

当前工作目录

所谓的当前工作目录是指启动程序的路径,也就是在那个路径启动程序,当前工作目录就是那个路径。为了验证这个事实, 跳转到家目录创建了一个file_test的目录,然后执行上层目录下的code目录下的可执行文件file_test。
在这里插入图片描述

同时,启动进程监控, 在/proc目录下得到file_test进程的相关信息,其中cwd所指向的就是当前工作目录。
在这里插入图片描述
查看当前工作目录,可知确实存在所创建的文件。
在这里插入图片描述

fputs

向文件中写入10行文本。
在这里插入图片描述
查看写入结果。
在这里插入图片描述

fgets

修改fopen的第二个参数为“r”。
在这里插入图片描述

查看运行结果。
在这里插入图片描述

由 C 文件操作引出的问题

文件的读写要先打开文件,那么为什么在Linux中一切皆文件,键盘和显示器都可认为是文件,但是我们没有打开文件,就可以使用printf和scanf分别往显示器打印和从键盘输入?

原因就是任何程序在运行时,操作系统都会为其打开三个文件,返回三个文件描述符,因此我们不需要打开,就可以从键盘和显示器分别读和写。

系统级别IO

打开文件

与 C 语言一样,C++ 或是 JAVA 在文件读写时默认都会打开三个文件,因此这三个文件的打开就不是单单一种语言实现,而是操作系统实现的。

在这里插入图片描述

执行上面代码,得到的结果是,每当我们创建出一个文件时,系统返回的文件描述符是从3开始,后面每打开一个文件,返回的文件描述在前一个基础上加一。这说明了,标准输入、标准输出和标准错误这三个文件在程序运行时就被指定映射到0 1 2三个文件描述符。其次,文件描述符类似于数组下标。
在这里插入图片描述

系统级别文件管理

从上面的代码可以看出,一个进程可以打开多个文件,系统中存在多个进程,这就意味着系统中可能存在多个打开的文件。因此,就需要对这些文件进行管理。系统为每个打开的文件用一个struct file描述,然后将多个结构体用双链表组织起来,进而实现对文件管理就是对双链表的增删查改。

文件构成

磁盘文件由文件内容和文件属性(元信息)构成。当打开磁盘文件时,就产生了内存文件,其中内存文件更多包含的是文件属性,当需要读或写数据时,数据采用的是延后式加载数据。

文件与进程关联

在进程描述结构体task_struct中有一个指向文件描述符指针数组。
在这里插入图片描述
当我们创建一个文件时,会在内存中创建一个struct file结构体描述内存文件。然后将结构体地址,也就是struct file*类型的地址填入到fd_array。当形成映射关系后,操作系统就会返回该文件在文件描述符指针数组中对应的下标。

所以文件描述符本质上就是数组下标。默认打开stdinstdoutstderr就是为这三者分别描述成struct file,然后将其关联到fd_array[0]fd_array[1]fd_array[2]

write底层流水线

在这里插入图片描述

read底层流水线

在这里插入图片描述

文件描述符的分配规则

从小到大,找到没被占用的即为打开的文件分配。

文件重定向

文件重定向本质就是改变fd_array中对应下标所指向的struct file,如下所示,向1号文件描述符写入,默认1号文件描述符指向显示器,写入的时候,会往显示器上写,但是当关闭1号文件描述符,再打开文件后,根据文件描述符分配规则,1号文件描述符就指向描述打开的文件的struct file。这样一来,指向变了,写入的文件也就变了。

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Schuyler Hu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值