Linux操作系统——重定向与缓冲区

1.理解一下struct file内核对象

上一篇文章(文件详解)我们一直在谈,一个文件要被访问就必须要先被打开,打开之前就必须要先把文件加载到内存,同时呢我们的操作系统为了管理文件也会为我们的文件创建相对应的struct file对象,那么这个struct file对象里面应该有什么?

其实struct file里面最核心的两个:一个叫做内容,另一个叫做属性。

因为我们前面说了文件= 内容+属性。所以一个文件被打开之后最重要的要么是内容,要么是属性。

如果我们要读一个文件,那么读文件一定是由进程来读的,其中进程的PCB中包含了一个文件描述符表指针指向struct file * fd_array[]数组的一个指针,正常情况下标准输入,标准输出,标准错误三个流是默认被打开的,也就是对应着文件描述符0,1,2,所以新打开的文件一般是把新打开创建的struct file的地址填到文件描述符为3的空间里,然后将该文件描述符作为返回值传递给上层,上层拿到了文件描述符为3的文件就可以对该文件进行一系列操作了。如果我们要对文件进行读数据,首先要将文件加载至内存,如果要对文件进行写数据时我们不能在磁盘中对文件进行写入,而是要把文件加载到缓冲区(内存空间)才能进行写入操作。所以说无论读写都要先把文件加载到文件缓冲区中!

那么我们在应用层进行数据的读写本质是什么呢?其实本质是将内核缓冲区中的数据进行来回拷贝!

下面我们看一看Linux内核源代码中关于文件的结构体字段的描述

2.文件描述符fd的分配规则

下面我们先看一下以写的方式打开文件如果不存在就创建文件的方式进行代码测试:

运行后:

既然我们说默认文件描述符为0,1,2的文件流默认是打开的,那么我们直接使用文件描述符为0的文件对其进行操作即可验证这一说法,然后改写代码为:

运行之后:

既然我们可以对标准输入进行读,那么自然也可以从标准输出进行写操作,下面我们将代码修改:

运行后:

读了abcdefg,同时写入了abcdefg.

进程默认已经打开了0,1,2,我们可以直接使用0,1,2进行数据访问!

下面我们在进行一些测试:

我直接把文件描述符为0的标准输入给关了

运行之后:

发现我们以写的方式打开的新的文件的文件描述符不再是3了,而是变成了0,一个该现象并不足以说明问题,下面我们把2号标准错误流给改了,看是否打开的新文件的文件描述符会发生变化。

运行结果:

我们发现果然,文件描述符变成了2,这说明了什么问题呢?

当我们打开一个新的文件时,会从文件描述符表中从上往下扫描,寻找文件描述符最小且没有被使用的文件描述符分配为为新的文件的文件描述符。

那么下面我们把文件描述符为1的标准输出流给关了之后会发生什么现象呢?

运行之后:

我们发现什么都没有???原因就在于我们原本printf是要将内容打印到显示上的,但是我们在代码中已经把文件描述符为1的标准输出流给关闭了,所以没有打印出来。

如果我们再把代码改成这样呢?

然后运行之后,再查看一下log.txt文件中的内容:

怎么我们要打印的内容在log.txt文件里面去了?

其实很容易理解,根据我们上面的结论,文件描述符为1的标准输出流关闭了,所以log.txt打开时会被分配最小的没有被使用的文件描述符,也就是1,所以当前情况下log.txt的文件描述符为1,而这些内容会写到log.txt里面原因就在于这个过程叫做输出重定向

3.重定向

printf只认stdout,而stdout只认_fileno=1也就是文件描述符为1所指向的文件,如果文件描述符为1指向的是显示器那就往显示器上打,如果文件描述符为1指向的是log.txt文件,那就往log.txt上打,所以说重定向的本质,其实就是修改特定文件fd的下表中的内容(也就是打开文件的地址)。

下面我们再使用一个与printf比较相似的fprintf来测试:

先看一下fprintf的手册:

编写如下代码:

运行之后:

下面我们把打开方式改一下:

运行之后:

所以我们就很容易的实现了追加重定向,每次运行都是在log.txt后面进行追加。

下面我们再测试一个输入重定向:

查看一下fread的相关手册

修改代码为如下:

运行结果:

我们发现原本应该要从键盘上读取数据,最后是从log.txt的文件上进行读取的。

所以上面就说明了,上层fd不变,底层fd指向的内容在改变。

关于上述的重定向我们感觉太麻烦了,因为它还需要我们关闭相对应文件描述符指向的文件,有没有一种方法是直接把新打开的文件的地址拷贝到对应文件描述符的内容里面去完成重定向呢?也就是通过文件描述符级别的数组内容的拷贝!

答案是有的,一下就是那个接口:

这个接口的用法是将oldfd的内容拷贝到,newfd上,也就是最后两处的文件描述符都是指向oldfd所指向的内容,而这会导致两个文件描述符如何关闭的问题,其实这个问题是文件结构体中会存在一个引用计数,也就是有几个指针指向该文件,如果有多个指针就对计数那个字段进行数量控制,如果有一个指向该文件的文件描述符关闭了,那么该字段就减减,直到减到0才关闭。下面我们以输出重定向为例来测试一下dup2这个接口:

运行结果:

这就叫做重定向。

4.缓冲区

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

低频信号发生器

前言 最近我快期末考试了,有点忙着复习。没时间写文章,不过学会了焊接 挺开心的所以买几套。 焊得怎么样这就是我们今天故事的主角“低频信号发生器”(由于要用到所以这是购买链接) 好,故事开始: 如何将…

基于Java (spring-boot)的社团管理系统

一、项目介绍 系统管理员的功能概述: ①用户管理 a.注册用户账户 当一个新用户注册时,用户填写基本信息并上传。用户基本信息包括账号、 姓名、密码、手机、地址等信息。 b.用户信息管理 管理员可以查看系统所有用户的基本信息,并修改和…

乡镇景区外卖需求的上涨,现在下场做外卖平台服务晚不晚?

如今,在田间地头点外卖已经变成了现实。随着外卖市场的发展,外卖消费的多样化场景逐渐显现,不仅在田间可以订餐外卖,出门旅行的任何地方都可以点上一份热腾腾的外卖送到面前。特别是从去年开始旅游经济恢复之后,外卖也…

【C初阶——内存函数】鹏哥C语言系列文章,基本语法知识全面讲解

本文由睡觉待开机原创,转载请注明出处。 本内容在csdn网站首发 欢迎各位点赞—评论—收藏 如果存在不足之处请评论留言,共同进步! 这里写目录标题 1.memcpy使用和模拟实现2.memmove的使用和模拟实现3.memset函数的使用4.memcpy函数的使用 1.m…

电阻表示方法和电路应用

电阻 电阻的表示方法 直标法 直标法是将电阻器的类别及主要技术参数的数值直接标注在电阻器表面上 通常用3位阿拉伯数字来标注片状电阻的阻值,其中第1位数代表阻值的第1位有效数;第2位数代表阻值的第二位有效数字;第3位数代表阻值倍率&…

力扣-刷MySQL(详细解析)

🎉欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克🍹 ✨博客主页:小小恶斯法克的博客 🎈该系列文章专栏:重拾MySQL 🍹文章作者技术和水平很有限,如果文中出现错误&am…

DataX的安装使用

DataX概述: DataX 是阿里巴巴集团内被广泛使用的离线数据同步工具/平台,实现包括 MySQL、Oracle、HDFS、Hive、OceanBase、HBase、OTS、ODPS 等各种异构数据源之间高效的数据同步功能。DataX采用了框架 插件 的模式,目前已开源,代…

救赎之道,就在其中

时光荏苒,不知不觉距离我踏入职场的第一天已经快一年了。最近也是看到平台举办年度征文活动,借此契机重新审视自己这两年来的成长历程,也希望对正在迷茫的人提供一些精神上的慰藉。 1.对未来的迷茫 如果要给两年前的自己打上标签&#xff0…

『 C++ 』AVL树详解 ( 万字 )

🦈STL容器类型 在STL的容器中,分为几种容器: 序列式容器(Sequence Containers): 这些容器以线性顺序存储元素,保留了元素的插入顺序。 支持随机访问,因此可以使用索引或迭代器快速访问任何位置的元素。 主要的序列式…

Hadoop 3.2.4 集群搭建详细图文教程

一、集群简介 Hadoop 集群包括两个集群:HDFS 集群、YARN 集群。两个集群逻辑上分离、通常物理上在一起;两个集群都是标准的主从架构集群。逻辑上分离 两个集群互相之间没有依赖、互不影响 物理上在一起 某些角色进程往往部署在同一台物理服务器上 MapR…

常见的反爬虫风控 | 验证码风控

一.前言 在当今信息技术迅速发展的背景下,网站和在线服务面临着日益增长的自动化访问威胁,这些大多来自于各类爬虫程序。这种大量的自动化访问不仅对网站的正常运行构成压力,还可能导致敏感数据的泄露,甚至被用于不正当竞争和恶意…

给 Linux 主机添加 SSH 双因子认证

GitHub:https://github.com/google/google-authenticator-android 在信息时代,服务器安全愈发成为首要任务。Linux 主机通过 ssh 方式连接,当存在弱密码的情况下,通过暴力破解的方式会很容易就被攻破了,本文将向你展示…

java的面向对象编程(oop)——static概述及初始单例设计模式

前言: 过了入门阶段,开始学习进阶语法了。每天进步一点点,打好基础,daydayup! 什么是面向对象编程(oop),可以看这篇 java的面向对象编程(oop)概述及案例 static概述 s…

亚信安慧AntDB超融合框架——数智化时代数据库管理的新里程碑

在信息科技飞速发展的时代,亚信科技AntDB团队提出了一项颠覆性的“超融合”理念,旨在满足企业日益增长的复杂混合负载和多样化数据类型的业务需求。这一创新性框架的核心思想在于融合多引擎和多能力,充分发挥分布式数据库引擎的架构优势&…

DBA技术栈(三):MySQL 性能影响因素

文章目录 前言一、影响MySQL性能的因素1.1 商业上的需求1.2 应用架构规划1.3 查询语句使用方式1.4 Schema的设计1.5 硬件环境 总结 前言 大部分人都一致认为一个数据库应用系统(这里的数据库应用系统概指所有使用数据库的系统)的性能瓶颈最容易出现在数…

什么是DDOS高防ip?DDOS高防ip是怎么防护攻击的

随着互联网的快速发展,网络安全问题日益突出,DDoS攻击和CC攻击等网络威胁对企业和网站的正常运营造成了巨大的威胁。为了解决这些问题,高防IP作为一种网络安全服务应运而生。高防IP通过实时监测和分析流量,识别和拦截恶意流量&…

Pixel手机进入工程模式、是否是Version版本?

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…

个人数据备份方案分享(源自一次悲惨经历)

文章目录 1 起源2 备份架构2.1 生活照片2.2 生活录音2.3 微信文件2.4 工作文件2.5 笔记、影视音乐、书籍 3 使用工具介绍3.1 小米云服务3.2 中国移动云盘3.3 小米移动硬盘(1T)3.4 FreeFileSync 4 总结 1 起源 本文的灵感源于我个人的一次不幸遭遇&#…

java自定义排序Comparator

📑前言 本文主要是【java】——java自定义排序Comparator的文章,如果有什么需要改进的地方还请大佬指出⛺️ 🎬作者简介:大家好,我是听风与他🥇 ☁️博客首页:CSDN主页听风与他 🌄每…

腾讯云主机价格表和优惠活动汇总(2024年更新)

腾讯云服务器租用价格表:轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年,540元三年、2核4G5M带宽218元一年,2核4G5M带宽756元三年、轻量4核8G12M服务器446元一年、646元15个月,云服务器CVM S5实例2核2G配置280.8元一年…