Linux 文件(2)

news2025/5/21 7:10:52

文章目录

  • 1. 文件描述符
    • 1.1 文件描述符是什么
    • 1.2 文件描述符如何分配
  • 2 重定向
    • 2.1 输出重定向
    • 2.2 输入重定向
    • 2.3 使用dup2进行重定向
  • 3. 文件、父子进程和进程替换

1. 文件描述符

1.1 文件描述符是什么

什么是文件描述符呢?

我们先来看之前所介绍的系统级别的文件操作函数open

在这里插入图片描述
在上图中,我们可以看到open有一个整型的返回值,而这个返回值,实际上就是文件描述符。

在Linux中,由进程打开文件,研究这些进程打开的文件,本质是研究文件与相应进程的关系。所以,在Linux中,会存在一个结构体用以描述文件:struct file。每一个被打开的文件,都会对应有一个struct file,这些struct file会被像双链表一样链接起来,就如task_struct一样。

而文件是由相应进程打开的,因此在描述进程的task_struct中,肯定要有记录其打开文件的变量,如下所示:

在这里插入图片描述
files这个指针指向一个files_struct的结构体,而在这个结构体中,存在一个指针数组,而这个指针数组中存放的就是一些struct file* 类型的变量,因此进程可以通过数组中存储的指针,找到其所打开的文件。

在这里插入图片描述

整体的关系可以如上图所示。

因此,文件描述符实质上就是上图中file* fd_array[]这个数组的下标。需要说明的是,操作系统识别进程打开的文件,是只通过这个文件描述符,即fd来识别的。

C语言中的FILE结构体用以描述文件,本质上是对struct file 的又一层封装,其中会存在文件描述符。

1.2 文件描述符如何分配

既然文件描述符就是数组的下标,那么文件描述符如何分派呢?

我们来看下面的测试程序:

在这里插入图片描述
上述程序的输出结果为:3
这有点奇怪,数组下标不都是从0开始的吗?这说明,0,1,2下标处,肯定对应的是别的文件。

实际上,一个进程启动时,会默认打开三个文件:标准输入stdin标准输出stdout标准错误 stderr。这三个文件,分别对应的就是数组下标0,1,2。

实际上,文件描述符是这样来分配的:返回从数组下标0开始,往后找到的第一个为空的数组下标处,即作为相应的文件描述符。

我们可以来测试一下,将标准输入文件关闭掉,然后再打开一个文件,此时这个文件的文件描述符应为0。

在这里插入图片描述
在这里插入图片描述
我们同样可以验证,进程启动时会默认打开stdin stdout stderr这三个文件,并且分配文件描述符0,1,2.

在这里插入图片描述

上述程序的输出结果为:

在这里插入图片描述
特别地,在上述代码中,我们拿到这三个文件的文件描述符是通过C语言中FILE这个结构体得到的,而在Linux中,文件描述的结构体是struct file,由此可见,C语言不仅对操作系统的接口做了封装,对操作系统的数据结构也会做封装。

2 重定向

什么是重定向呢?
正常情况下,我们输入是从标准输入中读取,而输出则是向标准输出中输出。重定向的核心就在于,使得输入不再从标准输入中读,输出不再向标准输出中输出。

2.1 输出重定向

我们先来看下面的示例:

在这里插入图片描述
我们来看上述程序的运行结果:

在这里插入图片描述
很奇怪,并没有显示出我们想要打印出的字符串。
printf函数默认是向标准输出中打印,实质上,我们前面讲过,操作系统层面,识别进程打开的文件,仅通过文件描述符实现。C语言中的printf本质是对系统调用write的封装,而write写入到哪里,正是通过文件描述符进行判定的。

因此,printf实质上是对该进程中,文件描述符为1的文件中写入,虽然我们先关闭了标准输出文件,但是新打开的文件,自动分配了文件描述符1,因此此时就会向这个新打开的文件中写入了。

我们查看一下log.txt中的结果,进行验证:

在这里插入图片描述

2.2 输入重定向

输入重定向与输出重定向是类似的。
C语言中的scanf默认是从标准输入中读取,实际上是从文件描述符为0的文件中读取。

我们通过下述代码,实现输入重定向:

在这里插入图片描述log.txt中的内容为hello linux,所以输入重定向读取一行字符串内容后,最终输出的结果也应为hello linux

最终输出结果如下所示:
在这里插入图片描述

2.3 使用dup2进行重定向

在这里插入图片描述

在这里插入图片描述

重点关注上述的dup2函数,这是一个可以实现重定向的系统调用。其原理是,让 newfd 变为oldfd 的拷贝。
比如说,我们要实现输出重定向,如果使用dup2系统调用,就不用先关掉标准输出文件,而是直接让原本存储标准输出文件的下标1处,变为存储我们要重定向到的文件。

以下,是使用dup2进行输出重定向和输入重定向的代码示例:

输出重定向:

在这里插入图片描述

输入重定向:

在这里插入图片描述

3. 文件、父子进程和进程替换

我们知道,进程打开文件,进程与文件之间是存在紧密联系的。

父进程创建子进程,子进程会继承父进程的代码和数据,子进程的task_struct也几乎是对父进程的拷贝,那么对于父进程打开的文件,子进程如何看待呢?

子进程会继承父进程打开的文件,即一个文件会对应多个进程,某文件在父进程中是打开的,那么这个文件在相应的子进程中也是打开的。
并且,在描述文件的结构体内部,存在一个引用计数,当一个文件对应多个进程时,引用计数为所对应的进程数,当一个进程关闭该文件时,引用计数便会减去1,直到引用计数为0时,该文件才会真正关闭。这也是进程具有独立性的一种体现——一个进程关闭某文件,并不会影响另一个进程对该文件的打开。

那么,进程替换中,会影响进程打开的文件吗?
答案是,不会的。进程替换,实质上并未新创建进程,而是对当前进程的代码和数据进行替换,主要更改的是进程地址空间、页表和物理内存这三者中相关映射,而进程task_struct中的其余内容并未有什么变化。
因此,某个进程在进程替换前有怎样的文件关系,在进程替换后,依然又怎样的文件关系,这是不会发生变化的。

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

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

相关文章

基于Springboot + vue3实现的工商局商家管理系统

项目描述 本系统包含管理员、商家两个角色。 管理员角色: 用户管理:管理系统中所有用户的信息,包括添加、删除和修改用户。 许可证申请管理:管理商家的许可证申请,包括搜索、修改或删除许可证申请。 许可证审批管理…

【Java ee初阶】HTTP(2)

一、HTTP的方法 方法 说明 支持的HTTP协议版本 GET 获取资源 1.0、1.1 POST 传输实体主体 1.0、1.1 PUT 传输文件 1.0、1.1 HEAD 获得报文首部 1.0、1.1 DELETE 删除文件 1.0、1.1 OPTIONS 询问支持的方法 1.1 TRACE 追踪路径 1.1 CONNECT 要求用隧道…

idea本地debug断点小技巧

idea本地debug断点小技巧 简单的设置断点条件 断点后,右键这个断点,可以在 condition 中填写能得出布尔的表达式 a 1 你如果写如下,表示先给他赋值,然后断住 a 2; true 断点后设置某个变量的值 在 debug 区域可以设置变量…

21. 自动化测试框架开发之Excel配置文件的测试用例改造

21. 自动化测试框架开发之Excel配置文件的测试用例改造 一、测试框架核心架构 1.1 组件依赖关系 # 核心库依赖 import unittest # 单元测试框架 import paramunittest # 参数化测试扩展 from chap3.po import * # 页面对象模型 from file_reader import E…

python-leetcode 69.最小栈

题目: 设计一个支持push,pop,top,操作,并能在常数时间内检索到最小元素的栈。 辅助栈法: 1:使用两个栈,一个主栈用于存储所有元素,另一个辅助栈用于存储当前元素的最小值 2: 每次push时,将元…

YOLO中model.predict方法返回内容Results详解

1.执行代码 resultsmodel.predict(YOLO/ultralytics/assets/zidane.jpg) print(results) 结果如下: 可以看出结果是一个数组形式,数组里每个元素都是Ultralytics的Results对象 1)为什么结果是数组,而不是单个对象? …

K8S详解(5万字详细教程)

目录 一、集群管理命令 二、命名空间 1. 获取命名空间列表 2. 创建命名空间 3. 删除命名空间 4. 查看命名空间详情 三、Pod 1. Pod概述 2. Pod相位状态 3. 管理命令 3.1 获取命名空间下容器(pod)列表 3.2 查看pod的详细信息 3.3 创建 && 运行 3.4 删除pod …

STL编程之vector

vector的基础概念&#xff1a;类 #include<iostream> #include<vector> using namespace std;int main() {int a[6] {1,2,4,5,6,7};vector<int> v { 1,3,6,8 };cout << v.capacity() << endl;v.push_back(8);cout << v.capacity() <…

BI是什么意思?一文讲清BI的概念与应用!

目录 一、BI 是什么意思 1. BI 的定义 2. BI 的发展历程 3. BI 的核心组件 二、BI 的应用场景 1. 销售与市场营销 2. 财务管理 ​编辑3. 人力资源管理 4. 生产与运营管理 ​编辑三、选择合适的 BI 工具 1. 考虑企业的需求和规模 2. 评估工具的功能和性能 3. 关注工…

[ 计算机网络 ] 深入理解TCP/IP协议

&#x1f389;欢迎大家观看AUGENSTERN_dc的文章(o゜▽゜)o☆✨✨ &#x1f389;感谢各位读者在百忙之中抽出时间来垂阅我的文章&#xff0c;我会尽我所能向的大家分享我的知识和经验&#x1f4d6; &#x1f389;希望我们在一篇篇的文章中能够共同进步&#xff01;&#xff01;&…

微软开放代理网络愿景

&#x1f310; Microsoft的开放式智能代理网络愿景 2025年05月20日 | AI日报 ![](https://i-blog.csdnimg.cn/direct/e7838b88f17f40c9a435f6dc48d26c59.jpeg#pic_center) 欢迎各位人工智能爱好者 微软刚刚在Build 2025大会上开启了备受期待的AI周活动&#xff0c;通过发布大…

4-5月份,思科,华为,微软,个别考试战报分享

一定要看正版学习资料&#xff0c;在资料上省的钱可能变成后面的补考费&#xff0c;#网络工程师 #华为考试题库 #HCIP题库 #HCIA题库 #HCSP题库 #HCSE题库 #HCSA题库 #华为电力题库 #华为金融题库 #正版题库#思科考试 #CCNP题库 #CCNA题库 #HCIA考试 #CCIE题库 #CCDE题库 #电信…

计算机网络-HTTP与HTTPS

文章目录 计算机网络网络模型网络OSITCP/IP 应用层常用协议HTTP报文HTTP状态码HTTP请求类型HTTP握手过程HTTP连接HTTP断点续传HTTPSHTTPS握手过程 计算机网络 网络模型 为了解决多种设备能够通过网络相互通信&#xff0c;解决网络互联兼容性问题。 网络模型是计算机网络中用于…

信号波形发生器电路Multisim仿真

一、电路 二、示波器 三、示波器波形 四、所遇到的问题 1、只是把电路仿真出来了&#xff0c;具体原理没有理解。 解&#xff1a; 第一个波形是正弦波&#xff0c;是由电阻和电容的振荡电路产生的。 第二个波形是方波&#xff0c;产生的正弦波通过电压比较器输出一个方波。…

Spring AI 介绍

Python一直是AI领域的主要语言, 主要原因是因其语法简洁易学、拥有丰富且强大的AI专用库及框架、具备跨平台兼容性且社区生态活跃,能高效支撑AI算法开发、数据处理及模型部署。 Spring开发了AI开发的框架Spring AI,对于Java的开发者来说,也可以快速入手AI相关的开发了。 S…

onlyoffice 源码 调试说明 -ARM和x86双模式安装支持

很多用户在调试onlyoffice源码最大的问题是如何搭建环境,这个难度很高,下面提供一键安装的方式,让普通用户也能快速调试源码。 OnlyOffice Document Server 基于源码运行的容器调试模式&#xff0c;凭借 Docker 容器化技术的核心优势&#xff0c;为开发者提供了跨平台、高兼容性…

EXCEL在一列数据前统一添加负号

1.全选数据列 2.右键&#xff0c;设置单元格格式。输入-0&#xff0c;要保留三位小数就输入-0.000. 3.添加完成效果。

UEFI Spec 学习笔记---33 - Human Interface Infrastructure Overview---33.2.6 Strings

33.2.6 Strings UEFI 环境中的 string 是使用 UCS-2 格式定义&#xff0c;每个字符由 16bit 数据表示。对于用户界面&#xff0c;strings 也是一种可以安装到 HIIdatabase 的一种数据。 为了本土化&#xff0c;每个 string 通过一个唯一标识符来识别&#xff0c;而每一个标识…

高等数学基础(牛顿/莱布尼茨公式)

牛顿/莱布尼茨公式主要是为定积分的计算提供了高效的方法, 其主要含义在于求积分的函数( f ( x ) f(x) f(x))连续时候总是存在一条积分面积的函数( F ( x ) F(x) F(x))与之对应, 牛顿莱布尼茨公式吧微分和积分联系了起来, 提供了这种高效计算积分面积的方法 参考视频理解: http…

2025年渗透测试面试题总结-华顺信安[实习]安全服务工程师(题目+回答)

网络安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 华顺信安[实习]安全服务工程师 1. 自我介绍 2. 红蓝队经验 3. Shiro漏洞知识体系 4. APP渗透测试方法…