重定向原理和缓冲区

文章目录

  • 重定向
  • 缓冲区

正文开始前给大家推荐个网站,前些天发现了一个巨牛的 人工智能学习网站, 通俗易懂,风趣幽默,忍不住分享一下给大家。 点击跳转到网站。

重定向

内核中为了管理被打开的文件,一定会存在描述一个文件的file结构体,这个结构体中大概有什么呢?
我们知道文件=文件内容 + 文件属性,所以file结构体中一定会存在打开文件的各种属性,其次它也一定存在自己的读写方法,也就是方法集,文件的内容是存在在磁盘中的,所以file中又一个属于内核级别的文件缓冲区,所以当我们读写文件的时候,是需要把文件的内容拷贝到文件缓冲区中的,然后如果读文件就把缓冲区中的内容拷贝到我们自己的定义的缓冲区中,如果写或者修改的话就把内容拷贝到内核缓冲区中,然后刷新到磁盘,所以我们在应用层进行的数据读写的本质就是将内核缓冲区的内容进行来回拷贝。不管是读文件还是写文件都需要先把内容拷贝到文件缓冲区。

fd的分配规则
进程是默认打开了0,1,2文件描述符的,我们在打开一个文件fd就是3,如果我们关闭了1,然后在进行打开文件,那么新打开的文件fd就是1,所以文件描述符的分配规则是遍历文件fd表,寻找最小的没有被使用的位置,然后分配给打开的文件。

重定向原理

重定向的就是把本来应该打印到显示器的内容打印了文件中,而往显示器打印本质就是想显示器文件打印,因为C语言中的标准输入输出本质就是封装了fd0和1,所以我们利用文件描述符的分配规则就可以自己实现一个简单的重定向功能。
如果我们要实现一个输出重定向的话,我们只需要把fd1关了,然后再打开一个文件,然后我们往显示器中打印内容,就会往fd1中打印,但是现在文件1指向的是我们自己新打开的文件。输入同理。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main()
{close(1);int fd = open("log.txt",O_WRONLY | O_CREAT | O_TRUNC , 0666);if(fd < 0) return -1;printf("hello printf\n");fflush(stdout);close(fd);return 0;
}

在这里插入图片描述
所以通过这种方式我们就可以自己实现一个输出重定向。但是我们每次都要自己关闭1号文件描述符,这样太麻烦了,那么如果存在一种可以把我们打开的文件的fd内容覆盖1号下标的内容就可以实现这个技术,所以重定向的本质就是修改文件描述符表。对于用户来说,fd是不变的,但是fd指向的内容改变了。系统中有一个函数dup2就可以实现这个功能。
在这里插入图片描述
dup2就可以让oldfd覆盖到newfd。对于被覆盖的文件,OS会自动帮你关闭的,所以我们通过这种方式也可以实现重定向功能。
以输入重定向为例:
dup2(fd,0)就可以实现下图的效果。
在这里插入图片描述
所以重定向的本质就修改文件描述符指向的内容,命令行级别的只需要对字符串进行特定的解析,然后调用dup2函数就可以实现重定向功能。程序替换时不会影响重定向的,因为程序替换只会替换代码和数据,对于进程的PCB是不影响的,所以对于PCB指向的文件fd

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>int main()
{int fd = open("log.txt",O_WRONLY | O_CREAT | O_TRUNC , 0666);if(fd < 0) return -1;//使用dup2dup2(fd,1);printf("hello hello\n");close(fd);return 0;
}

在这里插入图片描述
如果是对于追加和输入重定向的话,我们只需要控制一些打开文件时,打开的方式就可以实现,和输出同理。

我们知道标准输入和标准输出是我们平时使用必不可少的东西,所以系统会帮我们自动打开,这都没毛病,但是标准错误是什么东西??

#include <stdio.h>
int main()
{printf("i am printf\n");perror("i am perror ");return 0;
}

如果我们直接运行:
在这里插入图片描述
如果我们重定向一下:
在这里插入图片描述
可以通过这种方式把标准输出和标准错误打印的东西分开打印,perror和cerr都是向标准错误中打印,我们可以通过重定向把标准输出和标准错误打印的东西分别打印到不同的文件方便调试。

打印到同一个文件
在这里插入图片描述
打印到不同文件:
在这里插入图片描述

缓冲区

什么是缓冲区?
缓冲区的本质就是一快内存,用来存放数据的。

为什么要有缓冲区?
缓冲区的主要作用就是提高效率,谁使用缓冲区就提供谁的效率,因为有缓冲区的存在,我们在写一些东西的时候一定会涉及I/O操作,就一定会访问硬件,所以通过缓冲区累计一部分数据后再进行发送会远远比每次都进行I/O的效率要高很多。可以提高发送的效率。

缓冲区能够缓存一定的数据,就一定会存在自己的刷新策略:

  1. 全缓冲(缓冲区满了,在进行刷新)
  2. 行缓冲(行刷新)
  3. 无缓冲(立即刷新)

这三种是一般的策略,用户也可以通过fflush这样的函数来进行强制的刷新,并且在进程结束的时候,一般都要进行缓冲区的刷新的。一般对于显示器文件来说是行刷新,对于普通的磁盘文件是全刷新的。

我们可以通过一个样例来证明一下这个缓冲区的存在:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>int main()
{printf("hello printf\n");fprintf(stdout, "hello fprintf\n");fputs("hello fputs\n", stdout);char buffer[1024] = "hello write\n";write(1,buffer,strlen(buffer));pid_t id = fork();return 0;
}

这个代码很简单就不解释了,我们先直接运行一下,然后在重定向一下,看结果:

在这里插入图片描述
那么为什么会出现这个现象呢?

  1. 当我们直接运行的时候我们调用的所有接口都是向显示器文件打印,而显示器文件的刷新方式是行刷新,而我们所有的打印后面都有‘\n’,所以在fork()之前,我们的数据都已经被刷新了,包括write系统调用。
  2. 当我们重定向的时候,本质已经是向磁盘文件中打印了,不是向显示器文件打印了,所以刷新方式已经变成了全缓冲。
  3. 全缓冲就意味着缓冲区很大,当我们fork的时候,我们实际写入的数据很少,不足以把缓冲区打满,所以当fork的时候数据仍然在缓冲区中。
  4. 我们可以看到,重定向之后,只有C语言的接口打印了两次,而write系统调用只打印了一次,所以我们目前说的缓冲区是C语言提供的,和操作系统没有任何关系。也侧面证明了exit和_exit的区别,一个C语言提供的,程序退出刷新缓冲区,一个系统调用,不刷新缓冲区,所以这个缓冲区一定是C语言提供的。
  5. C/C++提供的缓冲区,里面保存的一定是我们用户的数据,只要我们不刷新,这个数据就属于我们用户,但是如果我们把缓冲区的数据写入了OS中,那么这部分数据就不属于我们了,而是属于OS。
  6. 当进程退出时一般都要刷新缓冲区,即使没有达到刷新的条件。而刷新的本质即使清空缓冲区,清空也是写入。所以当我们重定向向文件中打印的时候,系统调用会先先打,而C语言提供的接口打印的东西都还在C语言提供的缓冲区中,当我们fork创建子进程后,子进程会继承父进程的大部分数据,当子进程或者父进程退出时,退出的一方要刷新缓冲区,也就是写入,由于父子之间具有独立性,就要发生写时拷贝,这时,就出现了上面C语言接口打印两次的情况。

我们之前说过文件也有自己的文件缓冲区,也就是内核缓冲区,所以C语言的缓冲区和内核缓冲区的关系就是我们平时先把数据拷贝到C语言的缓冲区,根据刷新的机制在刷新到文件缓冲区,然后OS根据自己的安排定时刷新到磁盘。所以文件读写的本质就是来回拷贝。
在这里插入图片描述
从用户缓冲区拷贝到文件缓冲区的过程就是我们平时说的刷新。
我们在使用C语言的I/O接口是,都会接触FILE结构体,就连默认打开的3个流都是FILE指针类型。
在这里插入图片描述
因此C语言提供的缓冲区就是在FILE结构体中。所以FILE中不仅封装了fd文件描述符,还封装了缓冲区。

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

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

相关文章

4核8G配置服务器多少钱?2024年阿里云服务器700元1年价格便宜

4核8G配置服务器多少钱&#xff1f;2024年阿里云服务器700元1年价格便宜。阿里云4核8G服务器租用优惠价格700元1年&#xff0c;配置为ECS通用算力型u1实例&#xff08;ecs.u1-c1m2.xlarge&#xff09;4核8G配置、1M到3M带宽可选、ESSD Entry系统盘20G到40G可选&#xff0c;CPU采…

低噪声放大器是如何实现低噪声放大的功能的

灵敏度作为接收机最重要的指标之一,直接决定了接收机能分辨的最小信号。接收机的灵敏度计算公式如下所示。 Psensitivity=-174dBm+NF+10*lg(BW)+SNR 由接收机灵敏度的计算公式可知,影响接收机灵敏度的指标有噪声系数、带宽和信噪比,因此一旦带宽和信噪比确定了,那么能决…

C++ queue priority_queuestack 详解及模拟实现

1. stack的介绍和使用 1.1 stack的介绍 1. stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行元素的插入与提取操作。 2. stack是作为容器适配器被实现的&#xff0c;容器适配器即是对特定类封装作为其底层的容…

蓝桥杯(基础题)

试题 C: 好数 时间限制 : 1.0s 内存限制: 256.0MB 本题总分&#xff1a;10 分 【问题描述】 一个整数如果按从低位到高位的顺序&#xff0c;奇数位&#xff08;个位、百位、万位 &#xff09;上 的数字是奇数&#xff0c;偶数位&#xff08;十位、千位、十万位 &…

手机副业赚钱秘籍:让你的手机变成赚钱利器

当今社会&#xff0c;智能手机已然成为我们生活不可或缺的一部分。随着技术的飞速进步&#xff0c;手机不再仅仅是通讯工具&#xff0c;而是化身为生活伴侣与工作助手。在这个信息爆炸的时代&#xff0c;我们时常会被一种焦虑感所困扰&#xff1a;如何能让手机超越消磨时光的定…

移动端微信内置浏览器播放video不兼容无法自动播放的问题

移动端微信内置浏览器播放video不兼容无法自动播放的问题 先上公告 IOS中的解决方法 // 解决 ios 微信 video 自动播放document.addEventListener(WeixinJSBridgeReady,function() {const video document.querySelector(video);video && video.play();},false,);Vue中…

OpenStack云平台实战

1、环境准备 主机CPU数量内存硬盘IPV4发行版controller48GB100GBens33: 192.168.110.27/24 esn34: 192.168.237.131/24CentOS 7.9compute48GB200GB、100GBens33: 192.168.110.26/24 esn34: 192.168.237.132/24CentOS 7.9 1.1 虚拟机安装部署 1.1.1 创建虚拟机 这里16或者17都…

Ubuntu 20.04.06 PCL C++学习记录(二十五)

[TOC]PCL中点云分割模块的学习 学习背景 参考书籍&#xff1a;《点云库PCL从入门到精通》以及官方代码PCL官方代码链接,&#xff0c;PCL版本为1.10.0&#xff0c;CMake版本为3.16&#xff0c;可用点云下载地址 学习内容 使用渐进形态滤波器分割识别地面回波&#xff0c;即执…

SRIO系列-时钟逻辑与复位逻辑

一、前言 上一篇讲述了SRIO协议的基本概念&#xff0c;传输的HELLO帧格式、事务类型等&#xff0c;本篇说一下SRIO IP核的时钟关系。 基本的IP设置可以参考此篇文章&#xff1a;【高速接口-RapidIO】Xilinx SRIO IP 核详解-CSDN博客 二、时钟关系 PHY可以在两个时钟域上运行…

Windows 部署ChatGLM3大语言模型

一、环境要求 硬件 内存&#xff1a;> 16GB 显存: > 13GB&#xff08;4080 16GB&#xff09; 硬盘&#xff1a;60G 软件 python 版本推荐3.10 - 3.11 transformers 库版本推荐为 4.36.2 torch 推荐使用 2.0 及以上的版本&#xff0c;以获得最佳的推理性能 二、部…

3D Gaussian Splatting for Real-Time Radiance Field Rendering 在AutoDl上部署

目录 一. 租用AutoDl服务器二. Xtfp与服务器链接三. 本地训练准备数据3.1准备数据3.2 代码和模块下载 四. autodl环境配置4.1准备4.2 配置4.3 训练 五. 总结Reference 一. 租用AutoDl服务器 1.1 进入官网进行注册 1.2 点击算力市场租服务器&#xff0c;&#xff08;下图4090是…

论文笔记:Does Writing with Language Models Reduce Content Diversity?

iclr 2024 reviewer评分 566 1 intro 大模型正在迅速改变人们创造内容的方式 虽然基于LLM的写作助手有可能提高写作质量并增加作者的生产力&#xff0c;但它们也引入了算法单一文化——>论文旨在评估与LLM一起写作是否无意中降低了内容的多样性论文设计了一个控制实验&…

Boost电感的作用

Boost电感在Boost升压电路中起着关键的作用。Boost电路是一种DC-DC电源转换器&#xff0c;其主要功能是将低电压直流&#xff08;DC&#xff09;信号转换为高电压直流&#xff08;DC&#xff09;信号。Boost电感在这个过程中起着平滑电流、储存能量和提高电路效率的作用。 具体…

深入理解JVM中的G1垃圾收集器原理、过程和参数配置

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 在Java虚拟机&#xff08;JVM&#xff09;中&#xff0c;垃圾收集&#xff08;GC&#xff09;是一个自动管理内存的过程&#xff…

Matlab|【免费】基于SOE算法的多时段随机配电网重构方法

目录 1 主要内容 2 部分程序 3 部分模型级文献结果 4 下载链接 1 主要内容 该程序是完全复现《Switch Opening and Exchange Method for Stochastic Distribution Network Reconfiguration》&#xff0c;也是一个开源代码&#xff0c;网上有些人卖的还挺贵&#xff0c;本次…

Web前端 Javascript笔记1

为什么学习 JavaScript? JavaScript 是 web 开发人员必须学习的 3 门语言中的一门&#xff1a; HTML 定义了网页的内容CSS 描述了网页的布局JavaScript 控制了网页的行为 JavaScript 是可插入 HTML 页面的编程代码。 JavaScript 插入 HTML 页面后&#xff0c;可由所有的现代浏…

野生动物保护视频AI智能监管方案,撑起智能保护伞,守护野生动物

一、背景 在当今世界&#xff0c;野生动物保护已经成为全球性的重要议题。然而&#xff0c;由于野生动物生存环境的不断恶化以及非法狩猎等活动的盛行&#xff0c;保护野生动物变得尤为迫切。为了更有效地保护野生动物&#xff0c;利用视频智能监管技术成为一种可行的方案。 …

服务器数据恢复—ext3文件系统下raid5数据恢复案例

服务器数据恢复环境&故障情况&#xff1a; 某企业光纤存储上有一组由16块硬盘组建的raid5阵列。管理员发现该光纤存储上的卷无法挂载&#xff0c;经过检查发现raid5阵列中有2块硬盘离线&#xff0c;于是联系我们数据恢复中心要求数据恢复工程师到现场恢复服务器存储上的数据…

Vue3从入门到实战:深度掌握组件通信(下部曲)

5.组件通信方式5-$attrs $attrs的概念&#xff1a; 在Vue中&#xff0c;$attrs 是一个特殊的属性&#xff0c;用于访问父组件向子组件传递的非特定属性。它可以让子组件轻松地获取父组件传递的属性&#xff0c;而无需在子组件中显式声明这些属性。 想象一下你有一个父组件和…

pycharm debug 的时候 waiting for process detach

当你使用pycharm debug或者run的时候&#xff0c;突然出现了点不动&#xff0c;然后一直显示&#xff1a;waiting for process detach 可能是以下问题&#xff1a; 1、需要设置Gevent compatible pycharm一直没显示运行步骤&#xff0c;只是出现waiting for process detach-C…