【Linux】重定向|重新理解Linux下一切皆文件


文章目录

  • 一、什么是重定向
    • 输出重定向的原理
    • 认识一下输出重定向的系统调用
    • 输出重定向的另外写法
  • 二、浅谈输入重定向
  • 三、重定向和进程替换有冲突吗
  • 四、Linux下一切皆文件
  • 总结



一、什么是重定向

理解重定向之前:先理解一个叫做文件描述符的具体操作。

文件描述符,也是在上篇文章提到的,
在描述进程属性的PCB对象中存在着一个struct file*的指针,该指针指向一个指针数组,指针数组的每一个指针又指向对应的文件。

这个文件描述符,就是该指针数组的下标!

Linux的内核是这样实现的:

打开一个文件时,会在指针数组中找最近的一个空位置,存储该文件的地址。返回的文件描述符就是这个位置的下标。

在这里插入图片描述

先看下面的例子:

 8 #define filename "log.txt"9 int main()10 {11     int fd = open(filename, O_CREAT|O_WRONLY|O_TRUNC, 0666);12                                                                                                                           13     if(fd < 0)14     {15         perror("open fail");16         return 1;17     }18     const char* msg = "hello linux\n";19     int cnt = 5;20     while(cnt)21     {22         write(1,msg,strlen(msg));23         cnt--;24     }25     printf("%d\n",fd);26 }

从上面的代码不难看出,这里是打开一个log.txt的文件,并循环打印hello linux到显示器中。

运行结果也是在我们意料之中的。

当我在开头加上:

在main函数内的第一行加上:
close(1);

这段代码时:
在这里插入图片描述
会看到两个现象:

1.由于已经把1号文件,即标准输出流关闭了,所以fd文件描述符没有在屏幕上打印,是可以理解的。
2.在重新运行该程序前,我已经把log.txt文件删除,运行程序后,重新出现了log.txt文件并且在该文件中出现了本来应该打印在显示器文件的内容!!!

而这个现象,就是所谓的输出重定向!!!

输出重定向的原理

原理很简单:

在执行了close(1)后,1下标的文件描述符对应的指针就被置空了,同时维护stdout的引用计数也减减了,此时1号下标就是空的!!!
在这里插入图片描述

而在此之后,创建的新文件,会先从指针数组中查找最近的第一个空位置,并重新将该位置的指针指向新的文件,返回该下标!!!

在这里插入图片描述

也就是说,新打开的文件占用的是1号下标,返回的文件描述符是1!!!

这就解释了为什么本应该向显示器打印的内容,打印到了log.txt文件中,因为是该log.txt文件占用了1号下标的空间!!!

总结:所谓的输出重定向,就是将原来的文件向对应的文件数组中对象的地址做一次地址的拷贝!

认识一下输出重定向的系统调用

在这里插入图片描述

把oldfd拷贝到newfd中,最终两个文件fd都是oldfd。

举个简单的例子:

假设1号文件描述符存储的是text.txt file*

dup2(3,1);

在这里插入图片描述

就是将3号这个文件描述符拷贝到1号文件中覆盖,拷贝完成后,1位置下标和3位置下标对应的文件描述符都是3。

最终两个文件描述符都是3。

输出重定向的另外写法

假设test.c文件有如下内容

int main()
{fprintf(stdout,"hello stdout\n");                                                                                                       fprintf(stdout,"hello stdout\n");      fprintf(stdout,"hello stdout\n");      fprintf(stdout,"hello stdout\n");      fprintf(stderr,"hello stderror\n");      fprintf(stderr,"hello stderror\n");      fprintf(stderr,"hello stderror\n");      fprintf(stderr,"hello stderror\n");     return 0;
}

编译test.c文件生成test文件后。

执行如下命令:

./test 1>log.txt 2>&1

该代码的意思是:
./test可执行程序本应该向1号文件描述符对应的文件,即显示器文件中打印内容的,可是被重定向到了log.txt文件中,也就是log.txt文件对应文件描述符的内容拷贝到了1号文件的下标中。
所以./test 运行起来的四条printf语句会打印到log.txt文件中。

2>&1的意思是:将1号文件描述符中的指针内容拷贝给2好文件描述符中,本来2号文件描述符也是指向显示器文件的,至此也同样指向了log.txt文件。

所以log.txt文件会同时出现stdout和stderror两份打印内容。

./test >log.txt 2>&1

上面的命令还能这样写。也就是把1省略。因为默认就是打印到stdout上的。

二、浅谈输入重定向

输入重定向与输出重定向相反,默认从某一个文件中读取。

最简单的例子是:

cat < log.txt

从log.txt文件中读取到stdout显示器文件中。

三、重定向和进程替换有冲突吗

进程替换的本质只是将进程在物理内存中的代码和数据提换成磁盘文件中特定可执行程序的代码和数据。

替换前后并未创建新的进程,且替换后,只是修改了一下页表的映射关系,修改一下进程的虚拟地址空间中的几个参数值。

而重定向的本质是对文件描述符表中的指针进行拷贝,修改的文件描述符表的内容,与进程替换没有任何关系。

两者各司其职,产生了解耦关系。

未来该找进程的文件描述符表中的某一个下标文件写入时就写入,内存管理想向特定文件写入就写入,与文件描述符表的管理没有任何关系。

在这里插入图片描述

四、Linux下一切皆文件

我们平时按的键盘,看的显示器,网卡,声卡,磁盘等等,这些在Linux下都是文件,也就是我们平时所说的外设。

这些外设也是文件。
所以也有文件所有的读方法,写方法,其他的文件属性等等。

当我们想从键盘中输入一些东西时,首先要打开键盘文件。

打开前操作系统会做好一系列准备工作。

创建进程的PCB结构体对象task_struct,该结构体对象中能找到管理文件的文件结构对象(files_struct)

同事,这些外设本来就提供有属于它们独有的访问文件的读写方法等。

并且,每一个文件在被打开时,都会创建属于自己的文件对象struct file,这个文件对象中保存该文件的各种属性信息,其中就有两个函数指针,分别是读指针和写指针,指向该文件的读写方法。

在文件结构对象表files_struct中有一个文件描述符数组,该数组存储的是各个文件的文件描述符。

通过这些文件描述符即可找到对应的每一个被打开的文件。

而这一系列准备工作完成后,假设进程开始调度键盘文件。
该进程就是read系统调用。
read这个进程被运行起来,其内部有这样一条核心代码:

ssize_t read(int fd)
{task_struct->files_struct->fd_arr[fd]->f_opes->write();
}

首先进程去到自己的task_structPCB对象中找到文件对象表,在该表中获取到文件描述符,通过文件描述符找到了对应的文件对象,再通过文件对象中的一个指针找到描述对应文件的读写方法结构体,然后通过该结构体内的读写方法指针获取到对应的读写方法,再由该方法调用到对应的外设!

在这里插入图片描述

所以这就是我们之前经常所说的Linux下一切皆文件的原因!!!

这整个过程,就非常像C++中的多态!!!

所以可以肯定的是,C++的多态是抄C语言内核的,必定是这样!

任何一门语言要支持面向对象,它的底层一定会支持这样的思想结构。


总结

Linux下一切皆文件的本质就是面向对象的过程,对每个对象分层,串联起来就能实现调用不同的外设,就能实现不同的功能!!!

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

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

相关文章

【Qt之QWizardPage】使用

介绍 QWizardPage类是向导页面的基类。 QWizard表示一个向导。每个页面都是一个QWizardPage。当创建自己的向导时&#xff0c;可以直接使用QWizardPage&#xff0c;也可以子类化它以获得更多控制。 页面具有以下属性&#xff0c;由QWizard呈现&#xff1a;a title&#xff0c;…

JVM虚拟机-虚拟机执行子系统-第6章 字节码指令

字节码指令 Java虚拟机的指令由一个字节长度的、代表着某种特定操作含义的数字&#xff08;称为操作码&#xff0c;Opcode&#xff09;以及跟随其后的零至多个代表此操作所需的参数&#xff08;称为操作数&#xff0c;Operand&#xff09;构成。 字节码与数据类型 在Java虚拟…

uni-app 蓝牙打印, CPCL指令集使用

先上代码: GitHub - byc233518/uniapp-bluetooth-printer-demo: 使用uniApp 连接蓝牙打印机 Demo, CPCL 指令简单实用示例 (内含 芝珂,佳博,精臣 多个厂家指令集使用文档) 文件结构: ├── App.vue ├── CPCL 指令手册.pdf // 指令集参考手册 ├── LICENSE ├── R…

基于探路者算法优化概率神经网络PNN的分类预测 - 附代码

基于探路者算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于探路者算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于探路者优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络…

建造者模式(创建型)

目录 一、前言 二、建造者模式 三、链式编程实现建造者模式 四、总结 一、前言 当我们开发一个软件应用时&#xff0c;我们通常需要创建各种对象。有些对象是简单的&#xff0c;可以直接实例化&#xff0c;但有些对象则比较复杂&#xff0c;需要多个步骤才能创建完成。这时…

【备忘】websocket学习之挖坑埋自己

背景故事 以前没有好好学习过websocket&#xff0c;只知道它有什么用途&#xff0c;也知道是个好东西&#xff0c;平时在工作中没用过&#xff0c;所以对它并不知所以然。如今要做个自己的项目&#xff0c;要在付款的时候实时播报声音。自己是个开发者&#xff0c;也不想用别人…

解决升级docker导致的k8s崩溃问题

最近由于安装harbor升级了docker&#xff0c;然后发现k8s集群就启动不了。 查看kubelet日志发现&#xff1a;直接连不上apiserver了&#xff0c;直接connection refused 然后尝试启动apiserver容器直接报错&#xff1a;Error response from daemon: unknown or invalid runtim…

【原创】java+swing+mysql校园活动管理系统设计与实现

前言&#xff1a; 本文介绍了一个校园活动管理系统的设计与实现。该系统基于JavaSwing技术&#xff0c;采用C/S架构&#xff0c;使用Java语言开发&#xff0c;以MySQL作为数据库。系统实现了活动发布、活动报名、活动列表查看等功能&#xff0c;方便了校园活动的发布和管理&am…

线性表的概念

目录 1.什么叫线性表2.区分线性表的题 1.什么叫线性表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串… 线性表在逻辑上是…

餐厅订座预约小程序的效果如何

市场中无论哪种城市&#xff0c;餐厅非常多&#xff0c;一条不长的商业街&#xff0c;汇聚着数家餐饮品牌&#xff0c;且相互间竞争激烈&#xff0c;并且各个商家都希望用成本低高效率的方法引流及转化。 随着互联网深入各个行业&#xff0c;传统餐饮行业经营痛点不少。 传统餐…

前端---CSS的样式汇总

文章目录 CSS的样式元素的属性设置字体设置文字的粗细设置文字的颜色文本对齐文本修饰文本缩进行高设置背景背景的颜色背景的图片图片的属性平铺位置大小 圆角矩形 元素的显示模式行内元素和块级元素的转化弹性布局水平方向排列方式&#xff1a;justify-content垂直方向排序方式…

基于深度学习的活体人脸识别检测算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1. 活体人脸识别检测算法概述 4.2. 深度学习在活体人脸识别检测中的应用 4.3. 算法流程 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MATLAB2022a 3.部分核心程序 …

分形图案是什么?fpmarkets这样进入市场

分形图案的构造相对简单。市场在某个时间段内&#xff0c;会呈现单向的变动&#xff0c;要么持续上涨&#xff0c;要么持续下跌。观察这种趋势&#xff0c;并预测市场将呈现上涨态势后&#xff0c;过了一段时间&#xff0c;当所有有意向的买家都已经完成购买行为(即在价格上涨过…

EasyPOI实现excel文件导出

EasyPOI真的是一款非常好用的文件导出工具&#xff0c;相较于传统的一行一列的数据导出&#xff0c;这种以实体类绑定生成的方式真的非常方便&#xff0c;也希望大家能够了解、掌握其使用方法&#xff0c;下面就用一个实例来简单介绍一下EasyPOI的使用。 1.导入依赖 <!-- e…

C语言每日一题(31)相交链表

力扣160.相交链表 题目描述 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结构中不存在环。 注意…

新手老师怎么发布班级查询?

现在科技发展飞快&#xff0c;班级查询系统已经成为了许多学校必备的教务工具。可以让学生们快速查找到班级的各项信息&#xff0c;包括但不限于课程安排、考试成绩、分班等。对老师来说&#xff0c;班级查询系统可以提高工作效率&#xff0c;减少重复劳动&#xff0c;学生或者…

基于蝠鲼觅食算法优化概率神经网络PNN的分类预测 - 附代码

基于蝠鲼觅食算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于蝠鲼觅食算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于蝠鲼觅食优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神…

ubuntu中cuda12.1配置(之前存在11.1版本的cuda)(同时配置两个版本)

ubuntu中cuda12.1配置 由于YOLOv8项目中Pytorch版本需要cuda12.1版本 在官网下载12.1版本的deb包 官网地址 sudo dpkg -i cuda-keyring_1.0-1_all.deb sudo apt-get update sudo apt-get -y install cuda然后需要修改bashrc文件&#xff08;隐藏文件&#xff09; 添加 exp…

关系代数、SQL语句和Go语言示例

近些年&#xff0c;数据库领域发展日新月异&#xff0c;除传统的关系型数据库外&#xff0c;还出现了许多新型的数据库&#xff0c;比如&#xff1a;以HBase、Cassandra、MongoDB为代表的NoSQL数据库&#xff0c;以InfluxDB、TDEngine为代表的时序数据[1]库&#xff0c;以Neo4J…

jQuery UI简单的讲解

我们先进入一下问答时间&#xff0c;你都知道多少呢&#xff1f; &#xff08;1&#xff09;什么是jQuery UI 呢&#xff1f; 解答&#xff1a;jQuery UI 是以 jQuery 为基础的开源 JavaScript 网页用户界面代码库。包含底层用户交互、动画、特效和可更换主题的可视控件。我们…