【探索Linux】文件描述符 | 重定向 | 基础IO —— 强大的命令行工具 P.12

news2024/12/24 3:35:46

在这里插入图片描述

阅读导航

  • 前言
  • 一、open()函数返回值
  • 二、文件描述符fd
    • 1. 文件描述符的分配规则
    • 2. 文件描述符0、1、2
  • 三、重定向
    • 1. 重定向的本质
      • ⭕图解
    • 2. dup2 系统调用函数
  • 温馨提示

前言

前面我们讲了C语言的基础知识,也了解了一些数据结构,并且讲了有关C++的一些知识,也学习了一些Linux的基本操作,也了解并学习了有关Linux开发工具vim 、gcc/g++ 使用、yum工具以及git 命令行提交代码也相信大家都掌握的不错,上一篇文章我们了解了基础IO,文件操作,今天博主带大家了解一下 —— 文件描述符及重定向, 下面话不多说坐稳扶好咱们要开车了!!!😍

一、open()函数返回值

在认识返回值之前,先来认识一下两个概念: 系统调用库函数。上篇文章中我们提到的 fopenfclosefreadfwrite 都是C标准库当中的函数,我们称之为库函数(libc)。而, openclosereadwritelseek 都属于系统提供的接口,称之为系统调用接口

在Linux中,open()函数是用于打开文件的系统调用,它返回文件描述符。文件描述符是一个非负整数,用于唯一标识打开的文件。

open()函数的返回值有以下几种可能:

  • 如果成功打开文件,则返回一个新分配的文件描述符
  • 如果发生错误,返回-1,并可以使用全局变量errno获取具体的错误代码。

常见的错误代码包括:

  • EACCES:权限不足,无法访问指定文件。
  • ENOENT:文件不存在。
  • EISDIR:指定路径是一个目录。
  • EMFILE:进程已经达到了最大允许的打开文件数。
  • ENFILE:系统已经达到了最大允许的打开文件数。

使用时,我们一般需要检查open()函数的返回值是否为-1来判断是否出错,然后再根据具体的错误代码进行相应的处理。

二、文件描述符fd

1. 文件描述符的分配规则

文件描述符(File Descriptor)是一个整数,它用于标识一个进程打开的文件。在Unix/Linux系统中,每个进程都有一个文件描述符表(File Descriptor Table),用于管理打开的文件。文件描述符表是一个数组,每个元素表示一个打开的文件,而文件描述符就是数组的下标。

在Linux中,每个进程都有一个进程描述符(Process Descriptor)。进程描述符中包括一个文件描述符表,以及其他重要的信息,例如进程ID、进程状态等。当进程打开一个文件时,内核会从可用的文件描述符中选择一个最小的数字,并将其分配给该文件。这个数字就是文件描述符

文件描述符一般从3开始分配,因为0、1、2已经被预留给标准输入、输出、错误了。当进程打开一个文件时,内核会从当前可用的文件描述符中选择一个最小的数字,并将其分配给该文件。如果所有的文件描述符都已经被占用,再次打开文件就会返回错误。

当进程关闭一个文件时,相应的文件描述符就会变为可用状态,可以重新分配给其他文件。文件描述符的数目是有限的,通常与操作系统的版本、硬件配置等有关。

🚨🚨注意同一个进程中不同的文件描述符可以引用同一个文件,也就是说,打开同一个文件多次会得到不同的文件描述符。每个文件描述符都有自己的读写指针(File Offset),因此在不同的文件描述符上读写同一个文件,文件指针会互相独立,互不影响。

另外,在多进程编程中,父子进程共享文件描述符表。也就是说,如果一个进程打开了一个文件,并创建了一个子进程,那么子进程也会继承父进程的文件描述符表,包括已经打开的文件。这样,子进程就可以操作父进程已经打开的文件了。如果需要让子进程关闭父进程打开的文件,可以在fork()调用之后使用close()函数关闭不需要的文件描述符。

2. 文件描述符0、1、2

Linux进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0,标准输出1,标准错误2。这些文件描述符在进程启动时会自动打开,并与对应的设备文件关联起来。

具体来说:

  • 文件描述符0(stdin) 用于处理标准输入,也就是从键盘或管道中读取输入数据。
  • 文件描述符1(stdout) 用于处理标准输出,也就是将程序输出写入到屏幕上或者重定向到文件中。
  • 文件描述符2(stderr) **用于处理标准错误,也就是输出程序的错误信息到终端或者重定向到文件中。

这些文件描述符是预先打开的,因此无需使用open()函数来打开它们。使用时,可以直接使用文件描述符号码0、1、2来引用它们。
在这里插入图片描述

三、重定向

在Unix/Linux系统中,重定向是一种常用的操作,用于改变进程的标准输入、标准输出和标准错误输出的默认设备。通过重定向,可以将命令的输入来自文件,或者将输出和错误输出写入到文件中,而不是默认的终端设备

重定向可以使用以下符号进行操作:

  1. 标准输出重定向(>):使用大于号(>)将命令的标准输出写入到指定的文件中,并覆盖原有内容。如果文件不存在,则创建一个新文件。
    例如,将命令的输出写入到文件output.txt中:

    command > output.txt
    
  2. 标准输出追加重定向(>>):使用双大于号(>>)将命令的标准输出追加写入到指定的文件中,而不覆盖原有内容。如果文件不存在,则创建一个新文件。
    例如,将命令的输出追加写入到文件output.txt中:

    command >> output.txt
    
  3. 标准错误输出重定向(2>):使用大于号加数字2(2>)将命令的标准错误输出写入到指定的文件中,并覆盖原有内容。如果文件不存在,则创建一个新文件。
    例如,将命令的错误输出写入到文件error.txt中:

    command 2> error.txt
    
  4. 标准错误输出追加重定向(2>>):使用双大于号加数字2(2>>)将命令的标准错误输出追加写入到指定的文件中,而不覆盖原有内容。如果文件不存在,则创建一个新文件。
    例如,将命令的错误输出追加写入到文件error.txt中:

    command 2>> error.txt
    
  5. 标准输入重定向(<):使用小于号(<)将命令的标准输入从指定文件读取。
    例如,将命令的输入从文件input.txt中读取:

    command < input.txt
    

除了文件外,重定向还可以使用特殊设备:

  • /dev/null:空设备文件,将输出或错误输出重定向到/dev/null时,数据会被丢弃,类似于黑洞。例如:
    command > /dev/null   # 将命令的输出丢弃
    command 2> /dev/null  # 将命令的错误输出丢弃
    

重定向操作可以组合使用,例如:

command1 > output.txt 2>&1

上述命令将命令command1的标准输出和标准错误输出都写入到文件output.txt中。

🚨🚨注意重定向操作符(>、>>、2>、2>>、<)在使用时需要与命令之间有空格,否则会被当作命令的一部分处理。另外,重定向是由shell解释和处理的,不是由具体的命令实现的,因此在不同的shell中可能存在一些差异。

1. 重定向的本质

**重定向的本质是通过操作文件描述符来改变进程的输入输出。**当一个进程执行时,会从这三个文件描述符中读取输入或将输出写入其中。重定向就是改变这些文件描述符所对应的文件,从而改变进程的输入输出行为。

在重定向操作中,文件描述符0、1和2分别对应的是文件描述符表中的前三个元素,即0、1和2。通过操作文件描述符表,可以将文件描述符指向不同的文件或设备。

例如,当使用>符号重定向标准输出时,实际上是将文件描述符1所对应的文件更改为指定的文件。具体的操作步骤如下:

  1. 打开指定文件,获取其对应的文件描述符x。
  2. 将进程的文件描述符表中的1替换为x。

这样,当进程进行标准输出时,实际上是将数据写入到了指定的文件中。

类似地,其他重定向操作也是通过类似的方式改变文件描述符表中相应位置的文件描述符。

🚨🚨注意重定向操作只影响当前进程以及其子进程,不会影响其他进程。每个进程都有自己独立的文件描述符表,互不干扰。

⭕图解

在这里插入图片描述

2. dup2 系统调用函数

dup2是Unix/Linux系统提供的系统调用函数之一,用于复制文件描述符并将其关联到指定的文件描述符

使用dup2函数可以方便地进行文件描述符的重定向,实现输入输出的灵活控制

函数原型如下:

#include <unistd.h>
int dup2(int oldfd, int newfd);

参数说明:

  • oldfd:要被复制的文件描述符。
  • newfd:新的文件描述符,将与oldfd关联。

函数功能:
dup2函数将文件描述符oldfd复制到newfd,并返回一个新的文件描述符。如果newfd已经打开,则将先关闭它。新的文件描述符将继承oldfd的文件状态标志(例如,文件偏移量、文件访问模式等)。

函数返回值:

  • 成功时,返回新的文件描述符;失败时,返回-1,并设置errno变量来指示错误类型。

使用示例(输入重定向):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    int fd = open("file.txt", O_RDONLY);  // 打开文件,获取文件描述符
    if (fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    int newfd = dup2(fd, STDOUT_FILENO);  // 将文件描述符复制到标准输出
    if (newfd == -1) {
        perror("dup2");
        exit(EXIT_FAILURE);
    }

    printf("Hello, world!\n");  // 标准输出已被重定向到文件

    close(fd);  // 关闭文件描述符
    close(STDOUT_FILENO);
    return 0;
}

上述示例代码中,首先使用open函数打开一个文件,并获取文件描述符fd。然后,使用dup2函数将文件描述符fd复制到标准输出的文件描述符(即1),返回新的文件描述符newfd。接下来,通过printf函数向标准输出写入内容,实际上是将数据写入到文件中。最后,关闭文件描述符和标准输出的文件描述符。

温馨提示

感谢您对博主文章的关注与支持!如果您喜欢这篇文章,可以点赞、评论和分享给您的同学,这将对我提供巨大的鼓励和支持。另外,我计划在未来的更新中持续探讨与本文相关的内容。我会为您带来更多关于Linux以及C++编程技术问题的深入解析、应用案例和趣味玩法等。如果感兴趣的话可以关注博主的更新,不要错过任何精彩内容!

再次感谢您的支持和关注。我们期待与您建立更紧密的互动,共同探索Linux、C++、算法和编程的奥秘。祝您生活愉快,排便顺畅!
在这里插入图片描述

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

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

相关文章

Python常用函数中NumPy的使用教程

嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 1. txt文件 (1) 单位矩阵&#xff0c;即主对角线上的元素均为1&#xff0c;其余元素均为0的正方形矩阵。 在NumPy中可以用eye函数创建一个这样的二维数组&#…

合同管理系统

合同管理系统 功能介绍&#xff1a; 功能特性&#xff1a; 根据对合同管理系统系统分析合同管理由以下模块组成&#xff0c;相对方管理、合同文本管理、合同审批管理、合同履行审批、风险事件管理、合同查询、合同统计、系统提醒、系统管理。 1、相对方管理 1.有“相对方…

山西电力市场日前价格预测【2023-10-22】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2023-10-22&#xff09;山西电力市场全天平均日前电价为370.96元/MWh。其中&#xff0c;最高日前电价为612.26元/MWh&#xff0c;预计出现在18: 30。最低日前电价为216.57元/MWh&#xff0c;预计…

【换根DP】CF1882 D

Problem - D - Codeforces 思路&#xff1a; 一个很套路的换根 首先观察到&#xff0c;先对儿子一定比先对父亲操作来的代价小&#xff0c;因此考虑先对儿子操作&#xff0c;再对父亲操作 然后就可以直接换根了&#xff0c;首先考虑树形DP&#xff0c;设dp[u] 为 把 u 子树染…

Ubuntu系统下使用docker容器配置nginx并部署前端项目

1.下载 Nginx 镜像 命令 描述 docker pull nginx 下载最新版 Nginx 镜像 :2. 创建要挂载的宿主机目录 启动前需要先创建 Nginx 外部挂载的配置文件&#xff08; /home/nginx/conf/nginx.conf&#xff09; 之所以要先创建 , 是因为 Nginx 本身容器只存在 / etc/nginx 目录 ,…

京东数据平台:2023年9月京东净水器行业品牌销售排行榜!

鲸参谋监测的京东平台9月份净水器市场销售数据已出炉&#xff01; 根据鲸参谋平台的数据显示&#xff0c;今年9月份&#xff0c;京东平台净水器的销量为64万&#xff0c;环比下滑约9%&#xff0c;同比下滑约16%&#xff1b;销售额为5.2亿&#xff0c;环比下滑约12%&#xff0c;…

GO学习之 goroutine的调度原理

GO系列 1、GO学习之Hello World 2、GO学习之入门语法 3、GO学习之切片操作 4、GO学习之 Map 操作 5、GO学习之 结构体 操作 6、GO学习之 通道(Channel) 7、GO学习之 多线程(goroutine) 8、GO学习之 函数(Function) 9、GO学习之 接口(Interface) 10、GO学习之 网络通信(Net/Htt…

springboot缓存篇之mybatis一级缓存和二级缓存

前言 相信很多人都用过mybatis&#xff0c;这篇文章主要是介绍mybatis的缓存&#xff0c;了解一下mybatis缓存是如何实现&#xff0c;以及它在实际中的应用 一级缓存 什么是mybatis一级缓存&#xff1f;我们先看一个例子&#xff1a; GetMapping("/list") public…

折半搜索-oier复健练习题目

算法介绍&#xff1a; 折半搜索常用于复杂度O(n!)级的搜索问题&#xff0c;当我们发现很显然可以将问题划分为两部分分别搜索枚举&#xff0c;再合二为一求出最终答案时&#xff0c;我们可以选择使用折半搜索。 常见数据规模&#xff1a; 对于答案的值域往往没有要求&#x…

Jenkins自动化部署SpringBoot项目的实现

本文主要介绍了Jenkins自动化部署SpringBoot项目的实现&#xff0c;文中通过示例代码介绍的非常详细&#xff0c;具有一定的参考价值&#xff0c;感兴趣的小伙伴们可以参考一下 1、Jenkins介绍 1.1、概念 Jenkins是一个开源软件项目&#xff0c;是基于Java开发的一种持续集成…

shell算术运算符学习笔记

文章目录 算术运算符&#xff1a;算术运算扩展算术运算指令expr算术运算指令let自增自减运算符 算术运算符&#xff1a; 加法 - 减法 * 乘法 / 除法 % 取余 ** 幂运算算术运算扩展 算术运算扩展的运算数只能是整数 [rootlocalhost tmp]# num1$[41] [rootlocalhost tmp]# echo …

子类的构造与析构过程

一、简介 父类&#xff0c;也称基类&#xff0c;其构造方法和析构方法不能被继承&#xff1b; 子类&#xff0c;也称派生类&#xff0c;继承父类的方法和属性&#xff0c;但要加入新的构造和析构函数。 二、构造与析构过程 构造&#xff1a;先调用父类——>再调用子类 析构&…

STM32 HAL高级定时器正交编码模式案例

STM32 HAL高级定时器正交编码模式案例 &#x1f516;基于stm32F030RBT6单片机采用高级定时器1&#xff0c;编码器模式&#xff0c;测试EC11编码器。 &#x1f3ac;EC11测试效果&#xff1a; &#x1f33f;STM32定时器编码器有3种映射模式: ✨本次采用的是上面的模式3&#x…

同城外卖跑腿小程序开发的关键步骤

随着快节奏的生活方式和数字化技术的不断发展&#xff0c;外卖和跑腿服务变得越来越受欢迎。为了满足这一需求&#xff0c;越来越多的创业者和企业开始着手开发同城外卖跑腿小程序。本文将详细介绍同城外卖跑腿小程序开发的关键步骤&#xff0c;帮助您了解如何成功创建一个具有…

【Cesium】绘制线、面、体

文章目录 墙矩形长方体不规则图形椭圆椭圆柱正圆圆柱圆锥不规则多边形柱一串糖葫芦&#xff1f;带洞的矩形一系列矩形、圆形贴地的线围墙宽线宽线的体复杂线状体一根水管 墙 entities.add({wall: {id:"wall",positions: Cesium.Cartesian3.fromDegreesArray([-95.0,5…

java智慧工地云平台源码,以物联网、移动互联网技术为基础,结合大数据、云计算等,实现工程管理绿色化、数字化、精细化、智能化的效果

智慧工地将更多人工智能、传感技术、虚拟现实等高科技技术植入到建筑、机械、人员穿戴设施、场地进出关口等各类物体中&#xff0c;围绕人、机、料、法、环等各方面关键因素&#xff0c;彻底改变传统建筑施工现场参建各方现场管理的交互方式、工作方式和管理模式&#xff0c;智…

结构体内存分配与编译器对齐数

一、编译器对齐数 先说一个编译器的概念&#xff1a;对齐数。 1、对于基本类型的数据成员&#xff1a; 结构体的成员的对齐数min&#xff08;编译器对齐数&#xff0c;成员占内存大小&#xff09; 例如VS编译器对齐数位8&#xff0c;那么int型数据对齐数就为4&#xff0c;doubl…

如何理解OSI七层模型?

一、是什么 OSI &#xff08;Open System Interconnect&#xff09;模型全称为开放式通信系统互连参考模型&#xff0c;是国际标准化组织 ( ISO ) 提出的一个试图使各种计算机在世界范围内互连为网络的标准框架 OSI 将计算机网络体系结构划分为七层&#xff0c;每一层实现各自…

20T算力打造轻地图方案,这家智驾公司持续内卷

作者 | 张祥威 编辑 | 德新 行泊一体的话题热度不减。 近日&#xff0c;宏景智驾核心产品单SoC行泊一体解决方案已全场景跑通&#xff0c;可实现高速导航辅助驾驶。 在推进量产的同时&#xff0c;宏景智驾也在布局BEV感知、轻高精地图甚至去高精地图的智驾方案&#xff0c;同…

IPv6基础

1. IPv6概述 基本概念 IPv6&#xff08;Internet Protocol Version 6&#xff09;也被称为IPng&#xff08;IP Next Generation&#xff09;。它是Internet工程任务组IETF&#xff08;Internet Engineering Task Force&#xff09;设计的一套规范&#xff0c;是IPv4&#xff…