什么是文件描述符以及重定向的本质和软硬链接(Linux)

news2024/11/28 14:08:24

目录

    • 1 什么是文件?什么是文件操作?
      • 认识系统接口open
    • 什么是文件描述符
    • 认识Linux底层进程如何打开的文件映射关系
    • 重定向的本质
    • 理解软硬链接
    • 扩展问题

1 什么是文件?什么是文件操作?

文件 = 文件内容 + 文件属性(文件属性也是数据,即使你创建一个空文件,也要占据空间)
文件操作 = 文件内容操作 + 文件属性操作(有可能,在操作文件的过程中,既改变内容,又改变属性)
不管是学习语言还是学习操作系统,IO流是我们学习过程中不可获取的一个阶段,在这一部分我们会学习打开文件、读写文件等操作。
那所谓的“打开文件”,究竟是在干什么呢?其实就是将文件的属性或内容加载到内容中。
我相信大多数人的入门语言都是c语言,那我们就以c语言的文件操作进行举例;
如何理解printf?为什么调用printf就能往显示屏中打印内容呢?

其实printf是封装了系统的接口,然后由系统接口调用显示屏的驱动方法,然后进行打印

其实不管是C语言也好,Java也好,其他语言也罢,大多数的文件操作都是封装了系统接口。
封装的原因

  1. 原生系统接口使用成本比较高
  2. 语言不具备跨平台性(每个操作系统的接口可能不一样,写的代码可能只能在一个平台上跑)

封装是如何解决跨平台的问题的呢?

以c/c++方式举例:穷举所有底层接口 + 条件编译

在Linux系统调用接口中,我们打开文件使用open、关闭文件close、写入write、读取read。那这些接口和C中库函数接口有什么联系呢?我们可以这样理解:C中调用得这些库函数底层一定封装了系统调用接口,可以认为fopen底层调用open,fclose底层调用close,fread底层调用read,fwrite底层调用write。我们在windows中打开文件,windows底层也有一套自己的windows相关的api系统接口,当我们在windows使用C的库函数时,C调用的就是windows下的系统接口。这样在语言层面上就实现了跨平台性。
在这里插入图片描述

认识系统接口open

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>​
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

pathname: 要打开或创建的目标文件

flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags。

O_RDONLY: 只读打开

O_WRONLY: 只写打开

O_RDWR : 读,写打开

这三个常量,必须指定一个且只能指定一个

O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限

O_APPEND: 追加写
返回值:

成功:新打开的文件描述符

失败:-1

int main()
{
    umask(0);
    int fda = open("loga.txt",O_WRONLY | O_CREAT | O_TRUNC,0666);
    int fdb = open("logb.txt",O_WRONLY | O_CREAT | O_TRUNC,0666);
  
 
    printf("fda:%d\n",fda);
    printf("fdb:%d\n",fdb);
   
 
    close(fda);
    close(fdb);
   
    return 0;
}

运行结果:

fda:3
fdb:4

什么是文件描述符

OK,那前面描述怎么多,到底什么是文件描述符呢?其实系统接口open的返回值就是文件描述符。
Linux系统中,把一切都看做是文件,当进程打开现有文件或创建新文件时,OS向进程返回一个文件描述符,文件描述符就是OS为了高效管理已被打开的文件所创建的索引,用来指向被打开的文件,基本上所有执行I/O操作的系统调用都会通过文件描述符。简单来说,文件描述符可以唯一标识一个新打开的文件;类似学号,身份证号可以唯一标识一个人。
OK,引出概念后,我们来解决下面几个问题
上面那个例子中,为什么运行结果是3,4;或者说为什么是从3开始?

因为操作系统默认已经打开0,1,2号文件
0表示:标准输入,键盘
1表示:标准输出,显示器
2表示:标准错误,显示器

认识Linux底层进程如何打开的文件映射关系

** 为什么文件描述符是像0,1,2,3,4,5…,你见过什么样的数据,是这样子的?**

当然是数组的下标就是这样子的啦

首先在一个进程可以打开多个文件(就像我们写代码可以打开多个文件一样),那这么多文件,我们的OS要怎么管理呢?
一个文件被打开,在内核中,要创建该打开的文件的内核数据结构叫做struct file

struct file
{
 //包含了我想看到的文件大部分内容+属性
 struct file *next;
 struct file *prev;
}

再讲这个结构体file用类似链表的数据结构给串起来,所以对被打开的文件的管理,转化为对链表的增删改查
** 那进程如何和打开的文件建立映射关系呢?**
看下图
在这里插入图片描述
首先task_struct(进程控制块PCB)里面有一个字段是struct files_struct* files;files_struct里面有一个文件描述符表,其实就是一个array[]数组,里面存着结构体file的地址;当我们用户要打开一个文件时,先给你创建struct file这个结构体,初始化file内部属性还有函数指针指向的对应的方法,并且在当前进程的文件描述符表里分配一个没有被使用的下标,将新文件的地址(也就是结构体file的地址)给文件描述符表;然后会将这个新文件对应的文件描述符表的下标返回给用户,后面用户在调用read,write,一定传入了对应的文件描述符(fd),根据这个文件描述符就能找到对应的文件,对它做相应的操作。
那肯定有人问了,0,1,2 对应stdin,stdout,stderr 对应 键盘,显示器,显示器(这些都是硬件啊)也用你上面的struct file 来标识吗?

是的,在Linux下一下皆文件
在这里插入图片描述
在Linux下一切皆文件,结构体struct file里面有函数指针,指向的就是对应的IO方法(read,write),像磁盘啊,显示器啊,键盘啊,这些硬件,调用他们要调用对应设备的驱动方法,所以struct file的函数指针,指向这些对应设备的驱动方法。比如说标椎输出2号文件,结构体的函数指针就是指向显示器的驱动方法,将数据写到2号文件,也就是显示到显示屏上。

所以一切皆文件,举个例子,把显示屏看做文件,我们往显示屏打印数据,不就是往文件里写东西而已。

你可以验证一下上面的理论,先把标准输出1号文件关闭了,再打开log.txt文件,根据fd的分配规则,新的fd值一定是1;所以此时调用printf();本来printf是打印到1号文件,也就是显示屏;但是现在打印到log.txt文件里取了(当然这个过程也叫做重定向)
文件描述符的分配规则:从头遍历数组fd_array[],找到一个最小的,没有被使用的下标,分配给新的文件

int main()
{
 close(1);
 //根据fd的分配规则,新的fd值一定是1
 int fd = open("log.txt",O_WRONLY | O_CREAT | O_TRUNC,0666);
 if(fd < 0)
 {
     perror("oppen");
     return 1;
 }
 //printf-》stdout->1->虽然不在指向对应的显示器了,但是已经指向了log.txt的底层struct file 对象
     //本来应该要往显示器打印,最终却变成了向指定文件打印 -> 重定向
 printf("fd:%d\n",fd);
 //为什么必须要fflush一下
 fflush(stdout);
 close(fd);
}

重定向的本质

修改文件描述符fd下标 对应的struct file * 的内容 (将其换成目标文件的地址)。
重定向具体操作

int dup2(int oldfd,int newfd);//duplicate重定向
int main()

int fd = open("log.txt",O_WRONLY | O_CREAT | O_TRUNC,0666);
if(fd < 0)
{
  perror("open");
  return 0;
}
dup2(fd,1)>=0
//本来应该要往显示器打印,最终却变成了向指定文件打印 -> 重定向
fprintf(stdout,"打开文件:%d",fd);
fflush(stdout);
close(fd);
return 0;
}

在这里插入图片描述

理解软硬链接

在讲软硬链接之前,我们得先了解一下什么是inode。
我们刚才说的,打开的文件是内存级别的,实际上大量的文件还在磁盘上,这些文件和多,很杂,我们的文件系统就要对这些进行管理。
那么一个硬件(磁盘)怎么跟我们的OS产生联系呢?
把磁盘想象成为线性结构,当做500GB大小的数组,然后对磁盘的管理,转化为了对数组空间的管理。但是一次性管理500GB大小的数组不太可能,所以就对500GB的数组进行分区,一个区100GB,一个区还是太大,在对区进行分组;一个组10G;组内在细分成块,然后内核对这些块进行描述,比如有什么属性,属于哪个组;然后就转为对这些块的管理。
Linux 系统中就有一个名为 superblock 的 “硬盘地图”。 Linux 并不是把文件内容直接写入到 superblock 中,而是在里面记录着整个文件系统的信息。superblock里面就有一个叫inode的。
文件= 内容 + 属性——都是数据——都要存储

Linux采用的是将内容和属性数据分开存储的方案

内容一般放在(一块块)block中(4kb),属性数据一般放在inode中(inode说人话就是磁盘上的另一份空间,一般这份空间是128字节)

Linux 把每个文件的权限与属性记录在 inode("索引节点:index node ") 中,而且每个文件占用一个独立的 inode 表格,该表格的默认大小为 128 字节。

里面记录着如下信息 :

  • 文件的访问权限(read、write、execute)

  • 该文件的所有者与所属组(owner、group)

  • 该文件的大小(size)

  • 该文件的创建或内容修改时间(ctime)

  • 该文件的最后一次访问时间(atime)

  • 该文件的修改时间(mtime)

  • 文件的特殊权限(SUID、SGID、SBIT)

  • 该文件的真实数据地址(point)。

在 Linux 系统中 ,inode 号才是文件的唯一标识而非文件名。文件名只是为了方便人们的记忆和适用

那我现在知道了,inode就是文件的唯一标识,用来存储文件的属性的,那软硬链接到底是什么呢?

硬链接(hard link) : 可以将它理解为一个 “指向原始文件 inode 的指针”,系统不为它分配独立的 inode 和 文件。所以,硬链接文件与原始文件其实是同一个文件,只是名字不同。我们每添加一个硬链接,该文件的 innode 连接数就会增加 1 ; 而且只有当该文件的 inode 连接数为 0 时,才算彻底被将它删除。因此即便删除原始文件,依然可以通过硬链接文件来访问。需要注意的是,我们不能跨分区对文件进行链接。所以硬链接可以用来防止误删。
软链接(symbolic link) : 等同于 Windows 系统下的快捷方式。仅仅包括所含链接文件的路径名字。因此能链接目录,也能跨文件系统链接。但是,当删除原始文件后,链接文件也将失效。

软硬链接的区别:软链接是一个独立文件,有自己独立的inode和inode编号;硬链接,不是一个独立的文件,它和目标文件使用同一个inode

扩展问题

  1. 什么是硬链接数??

    此时的inode编号,不是就一个“指针”的概念吗?硬链接数本质就是给文件inode属性中的一个计数器count,标识有几个文件名和我的inode建立了映射关系。简而言之,就是有几个文件名,指向我的inode(文件本身)

  2. 既然软链接是一个独立的文件,那它的文件内容是什么呢??

    保存的是指向文件的所在路径

  3. 为什么创建普通文件,默认硬链接数是1;而创建目录,默认硬链接数是2呢??

    普通文件的文件名,本身就和自己的inode具有映射关系,所以是1;

    默认的空目录,有两个默认文件.和…,.表示当前目录,也指向这个目录,所以目录自己指向自己的inode,.也指向目录的inode,所以是2;而…指向的是上级目录的inode

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/620138.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

暴力递归到动态规划(二)

⭐️前言⭐️ 本篇文章是由暴力递归到动态规划篇章的第二篇。 &#x1f349;欢迎点赞 &#x1f44d; 收藏 ⭐留言评论 &#x1f4dd;私信必回哟&#x1f601; &#x1f349;博主将持续更新学习记录收获&#xff0c;友友们有任何问题可以在评论区留言 &#x1f349;博客中涉及源…

扫码出入库系统在哪些行业使用率最高?服务业绑得最紧密

什么是扫码出入库系统 扫码出入库系统是一种流行的库存管理系统&#xff0c;它使用二维码、条形码或RFID等技术来管理仓库内的物品出入库情况。 使用扫码出入库系统&#xff0c;用户可以通过扫描物品的二维码或条形码&#xff0c;快速地将物品信息录入系统中&#xff0c;同时…

采用sysbench压测mysql详解

文章目录 安装sysbench工具基于sysbench构造测试表和测试数据数据库读写性能测试数据库读性能测试数据库删除性能测试数据库更新索引字段性能测数据库更新非索引字段性能测试数据库插入数据性能测试数据库写性能测试执行完成压测之后可以将run改成cleanup&#xff0c;清除数据 …

LegalAI公开数据集的整理、总结及介绍(持续更新ing…)

诸神缄默不语-个人CSDN博文目录 最近更新日期&#xff1a;2023.6.7 最早更新日期&#xff1a;2023.6.7 文章目录 1. 司法判决预测2. 通用语料3. 其他集成项目4. 推理5. NLU6. NLG1 QA2 文本摘要 7. 信息抽取1 命名实体识别2 句子边界检测&#xff08;分句&#xff09; 1. 司法…

青岛科技大学|物联网工程|物联网定位技术(第二讲)|15:00

目录 物联网定位技术&#xff08;第二讲&#xff09; 1. 卫星的轨道高度与覆盖区域有何关系&#xff0c;试画图给予说明覆盖区地心角与覆盖面积的关系 2. 试给出实际的卫星地面覆盖区和用户空间可视区所对应的半地心角的公式并请给予解释 3. 定位导航卫星为什么一般不采用同…

【集群】LVS负载均衡群集

文章目录 前言一、企业群集应用概述1. 群集的含义1.1 群集的特点1.2 扩展服务器的方式 2. 群集的类型2.1 负载均衡群集&#xff08;Load Balance Cluster&#xff09;2.2 高可用群集&#xff08;High Availability Cluster&#xff09;2.3 高性能运算群集&#xff08;High Perf…

软考A计划-电子商务设计师-模拟试题卷七

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

有一种附件叫做V2附件

大家好&#xff0c;才是真的好。 一般而言&#xff0c;Notes中上传的附件都会对应到某个富文本字段中&#xff0c;这样附件易于处理&#xff0c;也容易进行排版。 最简单的案例就是我们的Notes邮件&#xff0c;附件可以附加在正文中&#xff0c;如下图&#xff1a; 还有我们…

新入职一家公司,接手了个从零开始的项目

开发流程 一个完整的从零开始开发的项目&#xff0c;会涉及到功能设计、数据库设计、项目框架搭建、接口设计与实现等流程&#xff0c;具体可以参考下图。 与我们后端开发有关的主要是功能设计、数据库设计、接口设计与实现这三部分&#xff0c;当然接口设计与实现中也包含项目…

chatgpt赋能python:Python如何快速SEO

Python如何快速SEO Python作为一种通用编程语言&#xff0c;广泛应用于各行各业&#xff0c;包括网站开发和SEO。SEO&#xff08;Search Engine Optimization&#xff09;是通过调整网站的结构和内容来提高其在搜索引擎排名中的位置&#xff0c;从而提高网站的流量和收益。Pyt…

【百问百答】可靠性基础知识第四期

1. IP等级的主要测试标准有哪些? 主要参考标准有GB 4208和IEC 60598&#xff0c; 其中也可以具体参考产品标准&#xff0c; 例如LED灯具参考标准为GB 7000&#xff0c; 汽车电子产品可以参考GB/T 28046.3等等。 2.IP等级可分为几个等级? 根据GB4208标准防止固定异物进入&…

阿里云 Serverless 容器服务全面升级:新增组件全托管、AI 镜像秒级拉取能力

6 月 1 日在阿里云峰会粤港澳大湾区上&#xff0c;阿里云智能云原生应用平台总经理丁宇宣布&#xff0c;Serverless 容器服务 ASK 全面升级&#xff0c;进一步帮助企业和开发者降本提效。 Gartner 曾预测&#xff0c;2023 年 70% 的 AI 应用将基于容器和 Serverless 技术开发。…

开源“上天入地”的本领都在这!2023 开放原子全球开源峰会「开源展览」一文拿捏!

2023 开放原子全球开源峰会 将于 6 月 11-13 日正式举办 开源领域新技术、新应用、新热点 Show Time&#xff01; 前沿开源展览汇 互动体验项目 让每一位参会者融入开源技术新世界&#xff01; 还有精彩的娱乐项目和丰厚礼品 一网打尽&#xff01; 抢先揭秘&#xff0c;一…

【Springboot】基于AOP机制的前置通知以及Cookies记录用户操作日志

文章目录 前言1. 添加依赖2. 创建自定义注解LogAnnotation3. 创建日志记录类型3. 编写切面逻辑4. 完善切面层&#xff0c;获取详细的请求信息4.1 获取自定义注解上的属性值4.2 通过Cookies获取用户信息4.3 获取执行时间4.4 日志实体类以及对应数据库类型 5.最后实现的结果 前言…

Spring Authorization Server扩展实现OAuth2.0的密码模式

写在前面 Spring官方已经停止对Spring Security Oauth2的维护&#xff0c;项目和相关文档也被移除 Spring Authorization Server是官方新推出的OAuth2.1和OpenID Connect1.0的实现 两个主要的版本&#xff0c;0.4.x&#xff1a;jdk8。1.x: jdk17 这里用的版本是0.4.1 OAuth2…

A Comprehensive Survey of Neural Architecture Search: Challenges and Solutions

这是NAS综述系列的第二篇文章&#xff0c;针对《A Comprehensive Survey of Neural Architecture Search:Challenges and Solutions》的翻译。 神经架构搜索综述&#xff1a;挑战与解决方案 摘要1 引言1.1 动机1.2 我们的贡献和相关综述1.3 文章组织 2 早期NAS的特征3 优化策略…

SpringBoot之Spring Data JPA入门学习2

我们继续使用上一章的环境。SpringBoot之Spring Data JPA入门学习 一、自动生成数据 我们修改一下实体 增加了几个注解&#xff1a; CreationTimestamp 自动生成创建时间。 UpdateTimestamp 自动生成更新时间。 使用这两个注解我们还需要在类上加上两个注解DynamicInsert和…

【unity造轮子】排序排行榜的制作

List类中有一个【Sort方法】 可以非常快速的对【整数类】 或者【小数类】元素进行升序 public class TestCompare MonoBehaviour {public List<int>numbers;private void Start(){numbersnew List<int>(){20,10,30,70,60,40,50,90,80,100}:}private void Update()…

stable diffusion图片资源分享和模型推荐,好用的模型有哪些呢?

前言 这篇文章主要是分享我的图片和推荐一些好用的模型&#xff0c;模型不在多在于精&#xff0c;基于几个好的大模型适当下载一下LORA模型&#xff0c;就能画出非常好的图片&#xff0c;多话不说 图片分享 简单展示 详情请看&#xff1a;https://space.bilibili.com/109890…

Amazon Web Services (AWS)上的 OpenText 信息管理(IM) 解决方案

Amazon Web Services (AWS)上的 OpenText 信息管理(IM) 解决方案 OpenText 行业领先的信息管理(IM) 解决方案作为完全托管的服务提供&#xff0c;以 Amazon 公有云环境的安全性、可扩展性和性能为后盾&#xff0c;实现业务数字化转型并推动创新。 价值 降低运营成本30%以上&…