当前位置: 首页 > article >正文

Linux 文件(2)

文章目录

  • 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中的其余内容并未有什么变化。
因此,某个进程在进程替换前有怎样的文件关系,在进程替换后,依然又怎样的文件关系,这是不会发生变化的。

相关文章:

Linux 文件(2)

文章目录 1. 文件描述符1.1 文件描述符是什么1.2 文件描述符如何分配 2 重定向2.1 输出重定向2.2 输入重定向2.3 使用dup2进行重定向 3. 文件、父子进程和进程替换 1. 文件描述符 1.1 文件描述符是什么 什么是文件描述符呢? 我们先来看之前所介绍的系统级别的文件…...

分析 redis 的 exists 命令有一个参数和多个参数的区别

在 redis 中,exists 命令是用来查询某个或多个 key 是否存在的,返回存在的 key 的个数。 由于 redis 是按照键值对方式存储数据的,于是一个 key 只能对应一组数据,那么上述的 key 的个数指的即是需要查询的 key 中有几个 key 是存…...

《具身智能机器人:自修复材料与智能结构设计的前沿探索》

在具身智能机器人的研发进程中,自修复材料与智能结构设计无疑是极具挑战性与创新性的关键领域,吸引着无数科研人员投身其中,探寻未知。 传统机器人在复杂多变的环境中执行任务时,一旦材料出现损伤,如外壳刮擦、内部线…...

Java 10IO流

IO流 input输入 output输出场景1:读写配置文件、日志文件 场景2:客户端与服务端的通讯 场景3:文件上传和下载io流体系结构 字节流 万能流,适合除纯文本文件外的储存字符流 纯文本文件字节流 FileOutputStream字节输出流 构造…...

@ColorRes和@ColorInt什么区别

ColorRes 和 ColorInt 都是 Android 的注解(Annotations),用于标记你传递的参数到底是什么类型的“颜色”信息——资源 ID 还是实际颜色值。 ✅ 一句话理解 注解代表含义举例通常用在ColorRes表示这是一个颜色资源 ID(如 R.colo…...

基于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…...

避开封禁陷阱:动态IP在爬虫、跨境电商中的落地实践

​​1. 为什么需要动态IP?​​ 在日常网络操作中,你是否遇到过: ​​爬虫被封​​:频繁请求目标网站,IP被限制访问。​​跨境业务受限​​:某些平台对特定地区的账号有限制。​​数据采集失败​​&#x…...

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)为什么结果是数组,而不是单个对象? …...

CF每日4题(1300-1400)

2026B 贪心 1300 我的思路和dalao很像 void solve(){int n;cin>>n;vector<int>a(n1);forr(i,1,n)cin>>a[i];int fg(n&1),ans;if(fg){ans1e1810;forr(i,1,n){//枚举把一个数去掉&#xff0c;其他两两组合int tmp1,j1;while (j<n){if(ji)j;int prea[j…...

golang学习大全

GO全路线学习&#xff08;总结&#xff09;大全 主题一 go语言基础知识讲解 go语言面向对象编程 go语言接口详解 go语言协程 主题二 web基础知识 构建web服务器 后续内容请大家持续关注&#xff0c;每月一主题&#xff0c;让各位读者能零基础、零成本学习go语言&#xff0c;我…...

falsk模型-flask_sqlalchemy增删改查

1、增、删、改 增 home_bp.route(/useradd) def user_add():users []for i in range(10,20):user User()user.name 冰冰 str(i)user.age 20iusers.append(user)try:db.session.add_all(users)db.session.commit()return jsonify({code:1,info:success})except Exception…...

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;通过发布大…...

UDP三种通信方式

单播&#xff08;Unicast&#xff09; 单播是最常见的通信方式&#xff0c;数据从一个发送方传输到一个特定的接收方。发送方将数据包发送到接收方的IP地址和端口号&#xff0c;接收方通过监听指定的端口接收数据。单播适用于一对一的通信场景。 import java.net.DatagramPac…...

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;产生的正弦波通过电压比较器输出一个方波。…...

深入解析Java微服务架构:Spring Boot与Spring Cloud的整合实践

深入解析Java微服务架构&#xff1a;Spring Boot与Spring Cloud的整合实践 引言 随着云计算和分布式系统的快速发展&#xff0c;微服务架构已成为现代软件开发的主流模式。Java作为企业级应用开发的核心语言&#xff0c;结合Spring Boot和Spring Cloud的强大生态&#xff0c;…...

医学影像辅助诊断系统开发教程-基于tensorflow实现

源码下载地址: https://download.csdn.net/download/shangjg03/90873910 1. 简介 医学影像辅助诊断系统是利用计算机视觉和深度学习技术,帮助医生分析医学影像(如X光、CT、MRI等)并提供诊断建议的系统。本教程将指导你开发一个基于深度学习的胸部X光肺炎检测系统。 2. 准备…...

前端单点登录

前端实现单点登录&#xff08;SSO&#xff09; 单点登录&#xff08;Single Sign-On&#xff0c;简称 SSO&#xff09;是一种认证机制&#xff0c;允许用户在多个系统之间只需登录一次&#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.添加完成效果。...