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.缓冲区

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

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

相关文章

数据库多表查询练习题

二、多表查询 1. 创建 student 和 score 表 CREATE TABLE student ( id INT ( 10 ) NOT NULL UNIQUE PRIMARY KEY , name VARCHAR ( 20 ) NOT NULL , sex VARCHAR ( 4 ) , birth YEAR , department VARCHAR ( 20 ) , address VARCHAR ( 50 ) ); 创建 s…

Qt6入门教程 6:Qt元对象系统

目录 一.什么是Qt元对象系统? 二.编译时Qt Creator偷摸做了哪些事情? 1.uic 2.rcc 3.moc 一.什么是Qt元对象系统? Qt中的元对象系统(Meta-Object System)提供了对象间通信的信号和槽机制、运行时类型信息和动态属…

uniCloud + uView 上传图片,删除图片(含u-upload 组件的使用)

上传图片 <u-upload imageModeaspectFit height"250" :maxCount1 :fileList"fileList" afterRead"uploadOK" delete"delPic"> </u-upload>::v-deep .u-upload__button {width: 100% !important; }::v-deep .u-upload__wra…

基于JAVA+SSM框架开发的志愿者服务管理系统设计与实现【附源码】

&#x1f345; 作者主页 央顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; &#x1f345; 查看下方微信号获取联系方式 承接各种定制系统 &#x1f4dd; &#x1f680;&#x1f680;&#x1f6…

RK3568笔记九: DRM显示摄像头

若该文为原创文章&#xff0c;转载请注明原文出处。 一、介绍 学习DRM的目的是想做类似NVR显示多路实时流&#xff0c;通过勇哥&#xff08;Marc)的指导&#xff0c;大概流程是通过Zlmedia拉流&#xff0c;RK3568的MPP解码,DRM显示&#xff0c;可以使用HDMI或DIS屏幕&#xf…

ssm+vue的物流配送人员车辆调度管理系统的设计与实现(有报告)。Javaee项目,ssm vue前后端分离项项目。

演示视频&#xff1a; ssmvue的物流配送人员车辆调度管理系统的设计与实现&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&…

【C++干货铺】会旋转的二叉树——AVLTree

个人主页点击直达&#xff1a;小白不是程序媛 C系列专栏&#xff1a;C干货铺 代码仓库&#xff1a;Gitee 目录 前言 AVL树 AVL树的概念 AVL树结点的定义 AVL树的插入 寻找插入结点的位置 修改平衡因子 AVL树的旋转 右单旋 左单旋 先右旋再左旋 先左旋再右旋 AVL树…

Kubernetes (十三) 存储——持久卷-动静态分配

一. 简介 二. NFS持久化存储步骤&#xff08;静态分配&#xff09; 1. 集群外…

数字信号处理教程学习笔记1-第2章时域中的离散信号和系统

信号处理的任务示意方框图 模拟信号和数字信号分别是啥样的,有啥区别

freetos day1

作业&#xff1a;使用计数型信号量设计&#xff1a;生产者和消费者模型 总结今天学习的API函数&#xff0c;写出函数参数和返回值的意思&#xff0c;并且说明函数功能 1 2 3

如何结合主从复制,不停服情况下解决分库分表

首先我们要知道主从复制和分库分表两个概念&#xff0c;在此基础上可以将问题分为几个阶段来执行&#xff0c;参考了公众号 双写读老 双写双读 写新读新

PHP反序列化漏洞原理

1、原理: 序列化与反序列化是保证数据一致性的过程。 2、产生: 序列化与反序列化的过程中,用户可控 如果反序列化的参数受到攻击者的控制,就会产生漏洞。攻击者可以通过修改参数个数等方式来控制反序列化过程,从而导致代码执行、SQL注入、目录遍历等不可控后果。如果在反…

2024年1月15日Arxiv最热论文推荐:斯坦福LLM精准微调新框架、GPT不愿承认回答错误、速度快15倍的3D全景分割新突破

本文整理了今日发表在ArXiv上的AI论文中最热门的TOP5。 论文解读、论文热度排序、论文标签、中文标题、推荐理由和论文摘要均由赛博马良平台上的智能体 「AI论文解读达人」提供。 如需查看其他热门论文&#xff0c;欢迎移步赛博马良 ^_^ TOP1 APAR: LLMs Can Do Auto-Paral…

【ARM 嵌入式 编译系列 7.3 -- GCC 链接脚本中 NOLOAD 和 GROUP 的详细介绍】

文章目录 NOLOAD 和 GROUP 的详细介绍NOLOAD 关键字GROUP 关键字实际应用案例 NOLOAD 和 GROUP 的详细介绍 在使用 arm-none-eabi-gcc 工具链中的链接器脚本时&#xff0c;链接脚本使用链接器命令语言来描述如何生成最终的可执行文件。其中&#xff0c;noload 和 group 是两个…

WEB 3D技术 three.js 3D贺卡(1) 搭建基本项目环境

好 今天 我也是在网上学的 带着大家一起来做个3D贺卡 首先 我们要创建一个vue3的项目、 先创建一个文件夹 装我们的项目 终端执行 vue create 项目名称 例如 我的名字想叫 greetingCards 就是 vue create greetingcards因为这个名录 里面是全部都小写的 然后 下面选择 vue3 …

代码随想录算法训练营Day21| 93.复原IP地址、78.子集、90.子集||

LeetCode 93 复原 IP 地址 本题思路&#xff1a;最重要的是想到一个收集结果的条件&#xff0c;也就是终止条件。 当 . 的个数达到三个时候&#xff0c;并且&#xff0c;判断最后剩余的是否符合要求&#xff0c;如果符合&#xff0c;说明整个ip地址可以&#xff0c;就加入到结…

【数据结构】C语言实现共享栈

共享栈的C语言实现 导言一、共享栈1.1 共享栈的初始化1.2 共享栈的判空1.3 共享栈的入栈1.3.1 空指针1.3.2 满栈1.3.3 入栈空间错误1.3.4 正常入栈1.3.5 小结 1.4 共享栈的查找1.5 共享栈的出栈1.6 共享栈的销毁 二、共享栈的实现演示结语 导言 大家好&#xff0c;很高兴又和大…

SpringBoot ElasticSearch 聚合统计

SpringBoot ElasticSearch 聚合统计 在SpringData Elasticsearch中&#xff0c;聚合统计的原理主要依赖于Elasticsearch本身的聚合框架。Elasticsearch提供了强大的聚合功能&#xff0c;使得你可以对文档进行各种计算和统计&#xff0c;从而得到有关数据集的有用信息。 Elasti…

Linux文件隐藏属性及chattr和lsattr命令

chattr命令 [rootstudy ~]# chattr [-] [ASacdistu] 文件或目录名称 选项与参数&#xff1a; &#xff1a;增加某一个特殊参数&#xff0c;其他原本存在参数则不动。- &#xff1a;移除某一个特殊参数&#xff0c;其他原本存在参数则不动。 &#xff1a;设置等于&#xff0c;且…

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

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