【Linux系统化学习】文件重定向

目录

文件内核对象

文件描述符的分配规则 

重定向

重定向的概念

dup2系统调用

输出重定向

追加重定向

输入重定向        

stderr解析

重定向到同一个文件中

分离常规输出和错输出


文件内核对象

上篇文章中我们介绍到了操作系统中的文件,操作系统为了方便管理进程打开的每个文件都会给每个文件创建一个内核对象(struct file)。但是每个进程可能打开多个进程,因此操作系统会形成一个数组,数组中的每个元素为文件内核对象指针指向当前进程打开的每个文件;数组的下标就代表一个打开的文件;对文件进行操作就是对数组的下标进行操作。打开的文件会加载在内存中,每个文件也都会有一段内存空间(文件缓冲区);打开文件会对文件进行操作,一般就是读操作和写操作;因此每个文件内核对象中一定含有这三种信息:

  • 打开文件的属性
  • 进行文件操作的方法集
  • 文件的内存空间(文件缓冲区)

总结:

  • 不能对磁盘中的内存进行操作,只能先将文件加载到内存中。
  • 对文件进行读数据和写数据都先要将文件加载到内存中(当文件不在内存中时会造成缺页中断,操作系统自动会将文件加载到内存中)。
  • 数据的读写本质是将内核缓冲区中的数据进行来回拷贝。

文件描述符的分配规则 

  1 #include<stdio.h>2 #include<sys/types.h>3 #include<sys/stat.h>4 #include<fcntl.h>5 #include<unistd.h>6 #include<string.h>7 #define FILE_NAME "log.txt"8 int main()9 {10 11     char buffer[1024];12     ssize_t s = read(0,buffer,1024);13     if(s>0)                                                              14     {15         buffer[s-1]=0;16         printf("echo# %s\n",buffer);17         write(1,buffer,strlen(buffer));18     }26     return 0;27 }

 

可以直接使用0和1文件描述符进行键盘和显示器的读写。 

    #include<stdio.h>2 #include<sys/types.h>3 #include<sys/stat.h>4 #include<fcntl.h>5 #include<unistd.h>6 #include<string.h>                                                       7 #define FILE_NAME "log.txt"8 int main()9 {10     int fd = open(FILE_NAME,O_CREAT|O_WRONLY|O_TRUNC,0666);11     if(fd<0)12     {13         perror("open");14         return 0;15     }                                                                    16     printf("fd:%d\n",fd);close(fd);17     return 0;18 }

 

上篇文章我们说过进程会默认打开三个流(stdin、stdout、stderr),分别为0,1,2。

文件描述符的分配规则:寻找最小的,没有被使用的数据的位置分配给指定的打开文件


重定向

重定向的概念

  • 改变原来系统命令的默认执行方式
  • Linux重定向是指修改原来默认的一些东西,对原来系统命令的默认执行方式进行改变,比如说简单的我不想看到在显示器的输出而是希望输出到某一文件中就可以通过Linux重定向来进行这项工作。

先执行一段代码,看现象:

    #include<stdio.h>2 #include<sys/types.h>3 #include<sys/stat.h>4 #include<fcntl.h>5 #include<unistd.h>6 #include<string.h>7 #define FILE_NAME "log.txt"8 int main()9 {10 11     close(1);12     int fd = open(FILE_NAME,O_CREAT|O_WRONLY|O_TRUNC,0666);13     if(fd<0)14     {15         perror("open");16         return 0;17     }18     printf("fd : %d \n",fd);19     printf("stdout->fd : %d \n",stdout->_fileno);fflush(stdout);close(fd)return 0;}

 

当我们不使用fflush刷新stdout时,显示器和新打开的文件都不会输出我们打印的内容,现象对应我们的第一张图片。使用fflush刷新stdout时,显示器不会输出我们的内容,但是新打开的文件中含有我们输出的内容。

现象的解释:进程运行是会打开我们的stdin、stdout、stderr,对应的文件描述符为0,1,2。当我我们关闭1,即关闭显示器。当新打开文件时根据文件描述符的分配规则文件描述符为1,但是printf、fprintf底层只认文件描述符1,但是此时的文件描述符已经不是stdout,而是新打开的文件,因此输出到新打开的文件中。

  1 #include<stdio.h>2 #include<sys/types.h>3 #include<sys/stat.h>4 #include<fcntl.h>5 #include<unistd.h>6 #include<string.h>7 #define FILE_NAME "log.txt"8 int main()9 {10 11     close(0);12     char buffer[1024];13     int fd = open(FILE_NAME,O_RDONLY);                                                                                                                   14     if(fd<0)15     {16         perror("open");17         return 0;18     }19     fread(buffer,1,sizeof(buffer),stdin);20     printf("%s\n",buffer);close(fd)return 0;}

 

根据上面的原理我们可以关闭0,即关闭从键盘输入;打开新文件,此时新文件的文件描述符为0,从新打开的文件中读取数据输入。 

dup2系统调用

通过上面的代码我们可以实现输入、输出重定向;但是需要我们手动关闭键盘或者显示器非常的麻烦,Linux中提供了系统调用,方便我们进行重定向。

  • 当调用dup函数时,内核在进程中创建一个新的文件描述符,此描述符是当前可用文件描述符的最小数值,这个文件描述符指向oldfd所拥有的文件表项。
  • dup2和dup的区别就是可以用newfd参数指定新描述符的数值,如果newfd已经打开,则先将其关闭。如果newfd等于oldfd,则dup2返回newfd, 而不关闭它。dup2函数返回的新文件描述符同样与参数oldfd共享同一文件表项。 

输出重定向

#include<stdio.h>2 #include<sys/types.h>3 #include<sys/stat.h>4 #include<fcntl.h>5 #include<unistd.h>6 #include<string.h>7 #define FILE_NAME "log.txt"8 int main()9 {10     int fd = open(FILE_NAME,O_CREAT|O_WRONLY|O_TRUNC,0666);11     if(fd<0)12     {13         perror("open");14         return 0;15     }16     dup2(fd,1);17     printf("fd : %d \n",fd);18     printf("stdout->fd : %d\n ",stdout->_fileno);19     printf("hello Linux\n");20     fprintf(stdout,"hello world\n");   close(fd);return 0;}             

  

使用系统调用进行重定向时,并不会像我们一样关闭键盘或者显示器而是创建新的文件描述符,然后让键盘或者显示器的文件描述符和键盘、显示器断开;和我们新打开的文件建立联系,此时这个文件就含有两个文件描述符,使用引用计数进行关闭文件。

追加重定向

#include<stdio.h>2 #include<sys/types.h>3 #include<sys/stat.h>4 #include<fcntl.h>5 #include<unistd.h>6 #include<string.h>7 #define FILE_NAME "log.txt"8 int main()9 {10     int fd = open(FILE_NAME,O_CREAT|O_WRONLY|O_APPEND,0666);11     if(fd<0)12     {13         perror("open");14         return 0;15     }16     dup2(fd,1);17     printf("fd : %d \n",fd);18     printf("stdout->fd : %d\n ",stdout->_fileno);19     printf("hello Linux\n");20     fprintf(stdout,"hello world\n");   close(fd);return 0;}    

输入重定向        

#include<stdio.h>2 #include<sys/types.h>3 #include<sys/stat.h>4 #include<fcntl.h>5 #include<unistd.h>6 #include<string.h>7 #define FILE_NAME "log.txt"8 int main()9 {10    // int fd = open(FILE_NAME,O_CREAT|O_WRONLY|O_APPEND,0666);11    int fd = open(FILE_NAME,O_RDONLY);                                    12     if(fd<0)13     {14         perror("open");15         return 0;16     }17     dup2(fd,0);18    // printf("fd : %d \n",fd);19    // printf("stdout->fd : %d\n ",stdout->_fileno);20    // printf("hello Linux\n");21    // fprintf(stdout,"hello world\n");22    char buffer[1024];23    fread(buffer , 1,1024,stdin);24    printf("%s",buffer);close(fd);return 0;}

stderr解析

上篇文章我们提到stdout和stderr,都代表显示器流即往显示器文件中打印。

#include<stdio.h>
int main()
{fprintf(stdout,"hello stdout\n");fprintf(stderr,"hello stderr\n");return 0;
}

 

但是我们进行重定向时只会将stdout进行重定向到文件中 ;stderr会在进程中保留。

因为fprintf底层只认文件描述符1,因此stderr不会被重定向。

重定向到同一个文件中

分离常规输出和错输出

进程运行时难免发生错误,输出错误信息;为了和常规信息进行区别,错误信息和常规信息分别独占一个显示器文件夹,我们只需要查看错误信息的显示器文件夹即可发现程序的报错信息。


今天对Linux下文件重定向的分享到这就结束了,希望大家读完后有很大的收获,也可以在评论区点评文章中的内容和分享自己的看法;个人主页还有很多精彩的内容。您三连的支持就是我前进的动力,感谢大家的支持!!! 

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

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

相关文章

代码随想录算法训练营第31天|● 理论基础 ● 455.分发饼干 ● 376. 摆动序列 ● 53. 最大子序和

文章目录 理论基础分发饼干思路&#xff1a;代码&#xff1a; 摆动序列思路一 贪心算法&#xff1a;代码&#xff1a; 思路二&#xff1a;动态规划&#xff08;想不清楚&#xff09;代码&#xff1a; 最大子序和思路&#xff1a;代码&#xff1a; 理论基础 贪心算法其实就是没…

开关电源电路主要元器件基础知识详解

在学习电子电路过程中&#xff0c;电源我们无法绕开的一个重要部分&#xff0c;很多时候&#xff0c;故障就出现在电源部分&#xff0c;特别是开关电源。开关电源电路主要是由熔断器、热敏电阻器、互感滤波器、桥式整流电路、滤波电容器、开关振荡集成电路、开关变压器、光耦合…

Slider滑动输入条(antd-design组件库)简单使用

1.Slider滑动输入条 滑动型输入器&#xff0c;展示当前值和可选范围。 2.何时使用 当用户需要在数值区间/自定义区间内进行选择时&#xff0c;可为连续或离散值。 组件代码来自&#xff1a; 滑动输入条 Slider - Ant Design 3.本地验证前的准备 参考文章【react项目antd组件-de…

linux系统下vscode portable版本的c++/Cmake环境搭建002:使用 VSIX 安装VSCODE插件(暂记)

使用 VSIX 安装VSCODE插件 在 Visual Studio Code (VSCode) 中&#xff0c;你可以通过以下步骤离线安装插件&#xff1a; 获取插件的 VSIX 文件&#xff1a; 在一个联网环境中&#xff0c;访问 Visual Studio Code Marketplace&#xff0c;搜索并找到你想要的插件。 比如&am…

1Coze平台介绍

2023年随着OpenAI推出GPT 3.5&#xff0c;AI赛道变得更加火热。GPT&#xff08;Generative Pre-trained Transformer&#xff09;是一种自然语言处理&#xff08;NLP&#xff09;模型&#xff0c;用于生成文本、理解语言和进行各种语言任务。GPT是由OpenAI开发的&#xff0c;它…

【Linux系统化学习】缓冲区

目录 缓冲区 一个样例 现象解释 缓冲区存在的位置 缓冲区 在刚开始学习C语言的时候我们就听过缓冲区这个名词&#xff0c;很是晦涩难懂&#xff1b;在Linux下进程退出时也包含缓冲区&#xff0c;因此缓冲区到底是什么&#xff1f;有什么作用&#xff1f; 让我们先从一个小…

拿捏c语言指针(上)

目录 前言 ​编辑 指针 内存与地址 计算机常见单位 理解编址 取地址&#xff0c;指针变量&#xff0c;解引用 取地址 指针变量 解引用 指针变量大小 指针类型的作用 char*解引用后 指针-整数 应用 void*指针 const修饰指针变量 const修饰普通变量 const修饰指…

【计算机网络】网络层之IP协议

文章目录 1.基本概念2.协议头格式3.网段划分4.特殊的IP地址5.IP地址的数量限制6.私有IP地址和公网IP地址7.路由 1.基本概念 IP地址是定位主机的&#xff0c;具有一个将数据报从A主机跨网络可靠的送到B主机的能力。 但是有能力就一定能做到吗&#xff0c;只能说有很大的概率。…

高校疫情防控系统的全栈开发实战

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

Django学习全纪录:Django开发环境的搭建

导言 对于Django&#xff0c;它是Python的一个开发框架&#xff0c;之前系统地学习过。遗憾的是&#xff0c;对于一些遇到的问题&#xff0c;没有及时地记录下来。因此&#xff0c;我将它重新捡起&#xff0c;进行学习和实践。从搭建环境开始&#xff0c;重新去学习它&#xff…

使用Taro开发鸿蒙原生应用——快速上手,鸿蒙应用开发指南

导读 本指南为开发者提供了使用 Taro 框架开发鸿蒙原生应用的快速入门方法。Taro&#xff0c;作为一个多端统一开发框架&#xff0c;让开发者能够使用一套代码同时适配多个平台&#xff0c;包括鸿蒙系统。文章将详细介绍如何配置开发环境&#xff0c;以及如何利用 Taro 的特性…

如何在CSS中实现背景图片的渐变?

--引言 在CSS中&#xff0c;实现背景图片的渐变通常需要使用linear-gradient或者radial-gradient函数&#xff0c;这些函数可以与背景图像一起使用来创建渐变效果。然而&#xff0c;CSS的渐变并不直接支持使用图像作为渐变的颜色停止点。但你可以通过一些技巧来实现类似的效果…

软件工程师,超过35岁怎么办

概述 随着科技行业的飞速发展&#xff0c;软件开发工程师的职业道路充满了各种机遇和挑战。对于已经在这个行业摸爬滚打了十多年的软件开发工程师来说&#xff0c;当他们步入35岁这个年纪时&#xff0c;可能会感到一些迷茫和焦虑。许多人担忧&#xff0c;在以创新、活力、快速迭…

代码随想录刷题笔记 DAY 28 | 复原 IP 地址 No.93 | 子集 No.78 | 子集 II No.90

文章目录 Day 2801. 复原 IP 地址&#xff08;No. 93&#xff09;1.1 题目1.2 笔记1.3 代码 02. 子集&#xff08;No. 78&#xff09;2.1 题目2.2 笔记2.3 代码 03. 子集 II&#xff08;No. 90&#xff09;3.1 题目3.2 笔记3.3 代码 Day 28 01. 复原 IP 地址&#xff08;No. 9…

Arrays工具类的常见方法总结

一、Arrays.asList( ) 1、作用 Arrays.asList( )可以将一个数组以集合的形式传入一个集合对象。通常用来将一组元素全部添加到集合中。 2、参数及返回值 参数&#xff1a;一组动态参数 返回值&#xff1a;List<T>集合 3、应用举例 List<String> boyListArra…

【知识整理】产研中心岗位评定标准之大数据岗位

为贯彻执行集团数字化转型的需要,该知识库将公示集团组织内各产研团队不同角色成员的职务“职级”岗位的评定标准; 一、定级定档目的 通过对公司现有岗位及相应岗位员工的工作能力、工作水平进行客观公正评定,确定各岗位的等级及同等级岗位员工对应的档级,从而为员工以后的晋升…

WordPress站点如何实现发布文章即主动推送到百度快速收录和普通收录?

我们在WordPress后台成功发布文章之后&#xff0c;如果靠搜索引擎来抓取的话&#xff0c;可能会比较慢&#xff0c;所以十分有必要将我们成功发布的文章马上提交到百度、必应等搜索引擎中。下面boke112百科就跟大家说一说WordPress站点如何实现发布文章即主动推送到百度快速收录…

函数、极限、连续——刷题(5

目录 1.题目&#xff1a;2.解题思路和步骤&#xff1a;3.总结&#xff1a;小结&#xff1a; 1.题目&#xff1a; 2.解题思路和步骤&#xff1a; 首先可能想到的是答案为0&#xff0c;但是不可以把 直接化简为n 这里要用到分子分母的平方差&#xff0c;sin^2的周期为π&#x…

【知识整理】招人理念、组织结构、招聘

1、个人思考 几个方面&#xff1a; 新人&#xff1a;选、育、用、留 老人&#xff1a;如何甄别&#xff1f; 团队怎么演进&#xff1f; 有没有什么注意事项 怎么做招聘&#xff1f; 2、 他人考虑 重点&#xff1a; 1、从零开始&#xff0c;讲一个搭建团队的流程 2、标…

【Anaconda】conda创建、删除、查看虚拟环境,安装pytorch

1.删除环境 首先退出现有的环境 conda deactivate然后查看要删除的环境名称与路径 conda env list接下来就可以删除环境了 有两种方法 方法1&#xff1a; conda env remove -p 要删除的虚拟环境路径对我来说就是&#xff1a; conda env remove -p D:\Anaconda3\envs\MVDet…