Linux文件系统——重定向

news2025/1/16 13:57:10

在这里插入图片描述

文章目录

    • 1. 文件描述符分配规则
    • 2. 重定向接口
      • dup2
      • 自定义shell重定向(补充)
    • 3. 标准输出和标准错误
    • 4. 如何理解一切接文件

本章代码gitee地址:文件重定向

1. 文件描述符分配规则

文件描述符的分配规则是从0下标开始,寻址最小的没有使用的数组位置,它的下标就是新文件的文件描述符。

我们来看一个现象:

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>

#define filename "log.txt"
int main()
{
  close(1);
  int fd = open(filename,O_CREAT|O_WRONLY|O_TRUNC,0666);
  if(fd < 0)
  {
    perror("open");
    return 1;
  }

  const char *str = "hello linux\n";
  int cnt = 5;
  while(cnt--)
  {
    write(1,str,strlen(str));
  }
  close(fd);
  return 0;
}

这段代码本应该是想1号文件描述符写入,也就是向显示屏输出信息。我们将这个1号文件描述符指向的显示器文件关闭了,运行结果没有显示出来,这个符合预期。可是,我们发现原本应该向显示器文件写入的内容,却写进了log.txt这个文件。

image-20231107190948481

这个过程就叫做——输出重定向

我们将1号文件描述符关闭,将进程与显示器对应的关联关系去掉。这个1号位置就空出来了,然后我们重新打开一个文件,那么正好1号文件描述符指向的内容是空的,然后就与该文件建立关联关系,所以内容写入这个文件

2. 重定向接口

如果我们想将某个内容重定向,其实不需要我们自己每次都手动关闭某个文件描述符,再去覆盖,系统为我们还提供了一些接口。

dup2

man 2 dup2

image-20231109105208160

这里的并不是拷贝文件描述符,因为文件描述符只是一个数组的下标,本质上拷贝的是文件描述符指向的内容

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>

#define filename "log.txt"
int main()
{
  //close(1);
  int fd = open(filename,O_CREAT|O_WRONLY|O_TRUNC,0666);
  if(fd < 0)
  {
    perror("open");
    return 1;
  }
  dup2(fd,1);
  close(fd);
  const char *str = "hello linux\n";
  int cnt = 5;
  while(cnt--)
  {
    write(1,str,strlen(str));
  }
  //close(fd);
  return 0;
}

image-20231109112020545

我们这里就能看到,原本应该向显示器文件输出的内容,重定向到了log.txt文件当中。

重定向的本质就是将文件描述表当中的文件地址做拷贝

自定义shell重定向(补充)

有了这些知识原理,就能写出自己的重定向代码

不了解的可以查看这篇文章——Linux实现简易shell

#define NONE -1
#define IN_RDIR 0
#define OUT_RDIR 1
#define APPEND_RDIR 2
char *rdirfilename = NULL;
int redir = NONE;

void check_redir(char *cmd)
{
  char *pos = cmd;
  while(*pos)
  {
    if(*pos == '>')
    {
      if(*(pos+1) == '>')
      {
        *pos++ = '\0';
        *pos++ = '\0';
        while(isspace(*pos))  pos++;
        rdirfilename = pos;
        redir = APPEND_RDIR;
        break;
      }
      else
      {
        *pos++ = '\0';
        while(isspace(*pos))  pos++;
        rdirfilename = pos;
        redir = OUT_RDIR;
        break;
      }
    }
    else if(*pos == '<')
    {
      *pos++ = '\0';
      while(isspace(*pos))  pos++;
      rdirfilename = pos;
      redir = IN_RDIR;
      break;
    }
    else
    {
      //不改变
    }
    pos++;
  }
}

void normalExcute(char *_argv[])
{
  pid_t id = fork();
  if(id < 0)
  {
    perror("fork fail");
    return; 
  }
  else if(id == 0)
  {
    //判断是否重定向
    int fd = 0;
    if(redir == IN_RDIR) //输入重定向
    {
      fd = open(rdirfilename,O_RDONLY);
      dup2(fd,0);
    }
    else if(redir == OUT_RDIR) //输出重定向
    {
      fd = open(rdirfilename,O_CREAT|O_WRONLY|O_TRUNC,0666);
      dup2(fd,1);
    }
    else if(redir == APPEND_RDIR)  //追加重定向
    {
      fd = open(rdirfilename,O_CREAT|O_WRONLY|O_APPEND,0666);
      dup2(fd,1);
    }
  
    //子进程执行命令
    //execvpe(_argv[0],_argv,environ);  //直接程序替换
    execvp(_argv[0],_argv);   //直接替换程序
    exit(EXIT_CODE);  //替换失败的退出码
  }
  else
  {
    //父进程等待子进程退出
    int status = 0;
    pid_t rid = waitpid(id,&status,0);  //阻塞等待
    if(rid == id)
    {
      lastcode = WEXITSTATUS(status);
    }
  }
}

这里的重定向并不会影响到之后的程序替换

因为这里的进程结构体或者是文件结构体,都是属于内核的数据结构,而我们的程序替换是由程序地址空间通过页表来进行一个替换,这也将程序替换和重定向工作进行了解耦

3. 标准输出和标准错误

标准输出stdou和标准错误stderr都是显示器文件输出内容,那他们这两个有什么区别呢

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>

#define filename "log.txt"
int main()
{
  fprintf(stdout,"hello stdout\n");
  fprintf(stdout,"hello stdout\n");
  fprintf(stdout,"hello stdout\n");


  fprintf(stderr,"hello stderr\n");
  fprintf(stderr,"hello stderr\n");
  fprintf(stderr,"hello stderr\n");
  return 0;
}

这里我们运行,确实是发现,都是往显示器文件上输出内容

image-20231111192917656

但是如果我们重定向,这里发现往标准错误输入的内容并没有重定向到我们的目标文件当中,而标准输出的内容被重定向到了目标文件

image-20231111193053970

通过这里我们可以验证,>这个输出重定向的符合,默认就是将一个号文件描述符的内容重定向到目标

image-20231111193321663

但是我们也可以指定将几号文件描述符指向的内容重定向到目标文件当中

这里有个2>&1,意思就是将一号文件描述符的内容拷贝到二号文件描述符当中,让其和1指向同一个文件

4. 如何理解一切接文件

所以操作计算机的动作,都是以进程的形式进行操作的;所以访问文件的操作,也都是以进程的形式访问的。

在计算机里面,存在着各种设备,例如键盘、显示器、磁盘、网卡…,这些都被称之为外设

操作系统和这些外设打交道的时候,都需要它们所对应的方法,例如显示要有读的方法、键盘要有读写方法…每个外设都要有其对应读写方法,这个简称为IO

因为在linux下一切皆文件,所以在操作系统看来,这些外设都是文件,而访问文件的操作,都是以进程的形式访问。linux内核里面又提供了一个方法表的结构struct operation_func,这里面包含了一些函数指针,函数指针可以调用这些外设的读写方法。

每打开一个文件,就会为其创建一个方法集对象,而在struct file中,又包含了一些指针,其中就有一个可以指向这个方法集。

那么在进程创建的时候,进程有对应的文件描述符表,这个表就能指向这些文件,我们用户就提供系统调用,来访问这些文件。

所以从这个struct file往上,我们并不用关心底层访问的是什么东西,我们看到就是一切皆文件

image-20231111210255538

这里指针指向哪一个对象,就访问哪一个对象,这个不就是多态的逻辑吗?

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

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

相关文章

飞机社交软件开发:重新定义社交媒体的空中交互体验

【导语】 随着互联网技术的快速发展&#xff0c;社交媒体平台的界限也逐渐模糊。飞机社交软件应运而生&#xff0c;打破传统的地面社交模式&#xff0c;为空中旅行的旅客提供全新的交流平台。本文将从市场需求、技术实现、用户体验和未来发展等方面&#xff0c;深入探讨飞机社交…

探索内存函数的奥秘【memcpy、memmove、memset、memcmp】

目录 一&#xff0c;memcpy函数 1&#xff0c;memcpy函数简介 2&#xff0c;memcpy函数的原理 3&#xff0c;memcpy函数的用法 4&#xff0c;注意事项 5&#xff0c;memcpy函数模拟实现 二&#xff0c;memmove函数 1&#xff0c;memmove函数简介 2&#xff0c;memmove函…

文件夹批量改名技巧:简单步骤,实现文件夹随机重命名

在日常生活和工作中&#xff0c;经常需要处理大量的文件夹&#xff0c;需要对其进行有效的管理。在这些情况下&#xff0c;文件夹的命名就变得非常重要。一个好的命名策略可以快速找到所需的文件夹&#xff0c;也可以帮助更好地组织文件。然而&#xff0c;手动为每个文件夹重命…

Ocelot:.NET开源API网关提供路由管理、服务发现、鉴权限流等功能

随着微服务的兴起&#xff0c;API网关越来越常见。API网关是连接应用程序和用户之间的桥梁&#xff0c;就像一个交通指挥员&#xff0c;负责处理所有进出应用的数据和请求&#xff0c;确保安全、高效、有序地流通。 今天给大家推荐一个.NET开源API网关。 01 项目简介 Ocelot…

通过easyexcel导出数据到表格

这篇文章简单介绍一下怎么通过easyexcel做数据的导出&#xff0c;使用之前easyui构建的歌曲列表crud应用&#xff0c;添加一个导出按钮&#xff0c;点击的时候直接连接后端接口地址&#xff0c;在后端的接口完成数据的导出功能。 前端页面完整代码 let editingId; let request…

智链引擎CEO李智:游戏化增长中台,让裂变营销快十倍、便宜十倍、好十倍丨数据猿专访...

大数据产业创新服务媒体 ——聚焦数据 改变商业 双十一电商大战一触即发&#xff0c;各个垂类的App也都希望能够借力双十一营销季&#xff0c;实现用户和营收双增长。MarTech在这个风口上&#xff0c;又成为2B赛道关注的焦点。 业内人士指出&#xff0c;MarTech的引入催生营销…

毅速丨金属3D打印零件品质受哪些因素影响

金属3D打印的零件品质受到多个因素的影响&#xff0c;包括设备、材料、工艺、后处理等。不同厂商的品质差别大致由以下几个方面造成。 一、设备性能差异&#xff1a; 不同厂商的金属3D打印设备可能存在性能上的差异&#xff0c;包括激光功率、扫描速度、打印精度、稳定性等。这…

【教3妹学编程-算法题】765. 情侣牵手

3妹&#xff1a;2哥2哥&#xff0c;你看到新闻了吗&#xff1f;襄阳健桥医院院长 公然“贩卖出生证明”&#xff0c; 真是太胆大包天了吧。 2哥 : 我也看到新闻了&#xff0c;7人被采取刑事强制措施。 就应该好好查查他们&#xff0c; 一查到底&#xff01; 3妹&#xff1a;真的…

Python:词法分析(行结构与显式、隐式行拼接)

相关阅读 Pythonhttps://blog.csdn.net/weixin_45791458/category_12403403.html?spm1001.2014.3001.5482 1、逻辑结构 一个Python程序由许多逻辑行组成&#xff0c;字面意义上的一行指的是末尾有换行符(\n)&#xff0c;但在不同的情况下&#xff0c;行末尾的换行符(\n)可能有…

如何选择一个可靠的爬虫代理服务商?技术人员都需要知道

我身边从事大数据相关行业的朋友最近告诉我&#xff0c;自己新招的小伙伴工作效率很低&#xff0c;很多最基础的工具都不会选择&#xff0c;经常因为代理IP不可靠导致工作出错。 听完这些我才意识到&#xff0c;在这个大数据时代&#xff0c;还是有很多新手在进行网络爬取任务…

Elasticsearch 和 Go 中使用向量搜索寻找地鼠

作者&#xff1a;CARLY RICHMOND&#xff0c;LAURENT SAINT-FLIX 就像动物和编程语言一样&#xff0c;搜索也经历了不同实践的演变&#xff0c;很难在其中做出选择。 加入我们的第二部分&#xff0c;通过 Elasticsearch 中的矢量搜索在 Go 中狩猎地鼠&#xff08;gophers&…

沁恒微WCH592程序烧录问题

在使用wch592蓝牙芯片时&#xff0c;使用WCHISPStudio_V3.60工具烧录hex固件时&#xff0c;识别设备OK&#xff0c; 擦除flash OK&#xff0c;就是在烧录时一直报错&#xff0c;错误如下&#xff1a; 原因是:代码和数据保护模式没有启用。 改为如下&#xff1a;

Git可视化界面的操作,SSH协议的以及IDEA集成Git

目录 一. Git可视化界面的操作 二. gitee的ssh key 2.1 SSH协议 2.2 ssh key 三. IDEA集成Git 3.1 分享项目 3.2 下载项目 一. Git可视化界面的操作 上一篇博客只用到了git的命令窗口&#xff0c;现在就来看看可视化窗口要怎么操作。 点击Git GUI Here GUI界面 在g…

由于找不到 d3dx9_43.dll,无法继续执行代码。重新安装程序可能会解决此问题

电脑出现d3dx9_43.dll缺失的问题&#xff0c;通常是由于DirectX组件未安装或损坏导致的。为了解决这个问题&#xff0c;我为您提供了以下四个解决方法&#xff1a; d3dx9_43.dll解决方法1. 使用dll修复程序修复 首先&#xff0c;使用系统文件程序dll进行修复操作非常简单&…

ZYNQ_project:IP_ram_pll_test

例化MMCM ip核&#xff0c;产生100Mhz&#xff0c;100Mhz并相位偏移180&#xff0c;50Mhz&#xff0c;25Mhz的时钟信号。 例化单口ram&#xff0c;并编写读写控制器&#xff0c;实现32个数据的写入与读出。 模块框图&#xff1a; 代码&#xff1a; module ip_top(input …

人工智能与养老:技术助力银色产业的崛起

人工智能与养老&#xff1a;技术助力银色产业的崛起 随着人口老龄化的加速推进&#xff0c;养老问题成为了全球关注的热点。人工智能&#xff08;AI&#xff09;技术的迅猛发展&#xff0c;为养老领域注入了新的活力。本文将探讨人工智能在养老领域的应用、关键挑战以及前景展望…

计算机毕业设计:水果识别检测系统 python 深度学习 YOLOv5

[毕业设计]2023-2024年最新最全计算机专业毕设选题推荐汇总 感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;希望帮助更多的人 。 1、项目介绍 本文介绍了一种基于深度学习的水果检测与识别系统…

【解决方案】pytion 运行时提示 import psutil ModuleNotFoundError: No module named ‘psutil‘

报错原因分析 import psutil ModuleNotFoundError: No module named psutil报错原因分析 当前环境pytion中缺少了psutil包&#xff0c;使用pip命令进行安装 解决方案 pip install psutil

十八数藏的新时代探索:数字创新助推文化保护

在这个数字化的新时代&#xff0c;传统文化和数字创新的结合呈现出令人振奋的新面貌。十八数藏&#xff0c;作为文化数字创新的佼佼者&#xff0c;正以数字化的手段助推文化的保护与传承。 十八数藏通过数字技术&#xff0c;将传统非物质文化遗产以数字形式呈现&#xff0c;使其…

【代码随想录】算法训练计划18

1、513. 找树左下角的值 题目&#xff1a; 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 思路&#xff1a; 递归&#xff0c;规则&#xff0c;基本可以自己写出来 var maxDepth int var res int fun…