当前位置: 首页 > news >正文

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

相关文章:

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

目录 文件内核对象 文件描述符的分配规则 重定向 重定向的概念 dup2系统调用 输出重定向 追加重定向 输入重定向 stderr解析 重定向到同一个文件中 分离常规输出和错输出 文件内核对象 上篇文章中我们介绍到了操作系统中的文件&#xff0c;操作系统为了方…...

防火墙工作模式详解

防火墙工作模式是指防火墙在网络中的工作方式和策略。常见的防火墙工作模式包括以下几种&#xff1a; 1. 包过滤工作模式&#xff1a;根据事先确定的规则集合&#xff0c;对进出网络的网络包进行过滤和检查。根据规则&#xff0c;防火墙可以允许或阻止特定的网络流量。 2. 代…...

CCF编程能力等级认证GESP—C++6级—20231209

CCF编程能力等级认证GESP—C6级—20231209 单选题&#xff08;每题 2 分&#xff0c;共 30 分&#xff09;判断题&#xff08;每题 2 分&#xff0c;共 20 分&#xff09;编程题 (每题 25 分&#xff0c;共 50 分)闯关游戏工作沟通 答案及解析单选题判断题编程题1编程题2 单选题…...

ES6 ~ ES11 学习笔记

课程地址 ES6 let let 不能重复声明变量&#xff08;var 可以&#xff09; let a; let b, c, d; let e 100; let f 521, g "atguigu", h [];let 具有块级作用域&#xff0c;内层变量外层无法访问 let 不存在变量提升&#xff08;运行前收集变量和函数&#…...

001 - Hugo, 创建一个网站

001 - Hugo, 创建一个网站安装hugoWindows系统Macos Hugo博客搭建初始化博客主题安装配置博客各个页面开始创作创建 GitHub Page 仓库本地调试和预览发布内容 教程及鸣谢文字教程视频教程 001 - Hugo, 创建一个网站 这篇文章假设你已经&#xff1a; 了解基本的终端命令行知识&…...

前端开发:Vue框架与前端部署

Vue Vue是一套前端框架&#xff0c;免除原生)avaScript中的DOM操作&#xff0c;简化书写。是基于MVVM(Model–View-ViewModel)思想&#xff0c;实现数据的双向绑定&#xff0c;将编程的关注点放在数据上。简单来说&#xff0c;就是数据变化的时候, 页面会自动刷新, 页面变化的时…...

【leetcode】深搜、暴搜、回溯、剪枝(C++)3

深搜、暴搜、回溯、剪枝&#xff08;C&#xff09;3 一、解数独1、题目描述2、代码3、解析 二、单词搜索1、题目描述2、代码3、解析 三、黄金矿工1、题目描述2、代码3、解析 四、不同路径III1、题目描述2、代码3、解析 一、解数独 1、题目描述 leetcode链接 2、代码 class…...

社区养老|社区养老服务系统|基于springboot社区养老服务系统设计与实现(源码+数据库+文档)

社区养老服务系统目录 目录 基于springboot社区养老服务系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员部分功能 &#xff08;1&#xff09; 用户管理 &#xff08;2&#xff09;服务种类管理 &#xff08;3&#xff09;社区服务管理 &#xff08…...

云计算基础-存储虚拟化(深信服aSAN分布式存储)

什么是存储虚拟化 分布式存储是利用虚拟化技术 “池化”集群存储卷内通用X86服务器中的本地硬盘&#xff0c;实现服务器存储资源的统一整合、管理及调度&#xff0c;最终向上层提供NFS、ISCSI存储接口&#xff0c;供虚拟机根据自身的存储需求自由分配使用资源池中的存储空间。…...

数学实验第三版(主编:李继成 赵小艳)课后练习答案(十二)(3)

实验十二&#xff1a;微分方程模型 练习三 1.分别用数值解命令ode23t和ode45 计算示例3中微分方程的数值解,同用命令ode23 算得的数值解以及解析解比较,哪种方法精度较高?你用什么方法比较它们之间的精度? clc;clear; f(x,y)2*yx2; figure(1) [x,y]ode23t(f,[1,2],1); plo…...

CSS Transition:为网页元素增添优雅过渡效果

随着互联网的发展&#xff0c;网页的视觉效果和用户体验变得尤为重要。CSS Transition作为一种能够让网页元素在状态改变时呈现平滑过渡效果的工具&#xff0c;受到了广大前端开发者的青睐。本文将详细介绍CSS Transition的基本概念、使用方法以及常见应用&#xff0c;帮助读者…...

JDK 17 新特性 (一)

既然 Springboot 3.0 强制使用 JDK 17 那就看看 JDK17 有哪些新特性吧 参考链接 介绍一下 新特性的历史渊源 JDK 17是Java Development Kit&#xff08;JDK&#xff09;的一个版本&#xff0c;它是Java编程语言的一种实现。JDK 17于2021年9月14日发布&#xff0c;并作为Java …...

杨中科 ASP.NET DI综合案例

综合案例1 需求说明 1、目的:演示DI的能力; 2、有配置服务、日志服务&#xff0c;然后再开发一个邮件发送器服务。可以通过配置服务来从文件、环境变量、数据库等地方读取配置&#xff0c;可以通过日志服务来将程序运行过程中的日志信息写入文件、控制台、数据库等。 3、说明…...

蓝桥杯嵌入式第12届真题(完成) STM32G431

蓝桥杯嵌入式第12届真题(完成) STM32G431 题目 程序 main.c /* USER CODE BEGIN Header */ /********************************************************************************* file : main.c* brief : Main program body**************************…...

C#系列-多线程(4)

在C#中&#xff0c;多线程编程主要涉及使用System.Threading命名空间下的类和接口来创建和管理线程。以下是一些C#多线程编程的基本用法和示例&#xff1a; 1. 使用Thread类创建线程 csharp代码 using System; using System.Threading; class Program { static void …...

VS如何调试C运行时库

C运行时库(简称crt)是C标准库等组件的基础, 其会在进入main函数之前运行一些代码, 包括但不限于初始化堆栈, 内存分配等操作     这些代码是可以随着VC工具集一起安装到我们本地的。看一下这个情况, 就是VS调试器没找到对应的crt源码的情况, 调用堆栈是空的。为了解决这个问…...

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

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

通过 Prometheus 编写 TiDB 巡检脚本(脚本已开源,内附链接)

作者丨 caiyfc 来自神州数码钛合金战队 神州数码钛合金战队是一支致力于为企业提供分布式数据库 TiDB 整体解决方案的专业技术团队。团队成员拥有丰富的数据库从业背景&#xff0c;全部拥有 TiDB 高级资格证书&#xff0c;并活跃于 TiDB 开源社区&#xff0c;是官方认证合作伙…...

sql语句学习(一)--查询

【有道云笔记】基本sql语句2—查询基础 数据库表结构 DROP TABLE IF EXISTS class; CREATE TABLE class (id int(11) NOT NULL AUTO_INCREMENT,class_num varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 班级号,class_name varchar(255) CHARACTE…...

【HTML】交友软件上照片的遮罩是如何做的

笑谈 我不知道大家有没有在夜深人静的时候感受到孤苦难耐&#xff0c;&#x1f436;。于是就去下了一些交友软件来排遣寂寞。可惜的是&#xff0c;有些交友软件真不够意思&#xff0c;连一些漂亮小姐姐的图片都要进行遮罩&#xff0c;完全不考虑兄弟们的感受,&#x1f620;。所…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

基于PHP的连锁酒店管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...

BLEU评分:机器翻译质量评估的黄金标准

BLEU评分&#xff1a;机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域&#xff0c;衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标&#xff0c;自2002年由IBM的Kishore Papineni等人提出以来&#xff0c;…...

人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent

安全大模型训练计划&#xff1a;基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标&#xff1a;为安全大模型创建高质量、去偏、符合伦理的训练数据集&#xff0c;涵盖安全相关任务&#xff08;如有害内容检测、隐私保护、道德推理等&#xff09;。 1.1 数据收集 描…...

苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会

在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...