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

这篇具有很好参考价值的文章主要介绍了【探索Linux】—— 强大的命令行工具 P.12(文件描述符 | 重定向 | 基础IO)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【探索Linux】—— 强大的命令行工具 P.12(文件描述符 | 重定向 | 基础IO),Linux,linux,运维,开发语言,服务器

前言

前面我们讲了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来引用它们。
【探索Linux】—— 强大的命令行工具 P.12(文件描述符 | 重定向 | 基础IO),Linux,linux,运维,开发语言,服务器

三、重定向

在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。

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

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

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

⭕图解

【探索Linux】—— 强大的命令行工具 P.12(文件描述符 | 重定向 | 基础IO),Linux,linux,运维,开发语言,服务器

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++、算法和编程的奥秘。祝您生活愉快,排便顺畅!
【探索Linux】—— 强大的命令行工具 P.12(文件描述符 | 重定向 | 基础IO),Linux,linux,运维,开发语言,服务器文章来源地址https://www.toymoban.com/news/detail-716436.html

到了这里,关于【探索Linux】—— 强大的命令行工具 P.12(文件描述符 | 重定向 | 基础IO)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【探索Linux】—— 强大的命令行工具 P.3(Linux开发工具 vim)

    前面我们讲了C语言的基础知识,也了解了一些数据结构,并且讲了有关C++的一些知识,也学习了一些Linux的基本操作,也相信大家都掌握的不错,今天博主带大家了解一下Linux开发工具—— vim ,下面话不多说坐稳扶好咱们要开车了!!!😍 Vim(Vi IMproved)是一款在Unix和类

    2024年02月12日
    浏览(30)
  • 【探索Linux】—— 强大的命令行工具 P.2(Linux下基本指令)

            前面我们讲了C语言的基础知识,也了解了一些数据结构,并且讲了有关C++的一些知识,也相信大家都掌握的不错,今天博主将会新开一个Linux专题,带领大家继续学习有关Linux的内容。今天第一篇文章博主首先带领大家了解一下什么是Linux,以及Linux的几个常用命令符

    2024年02月14日
    浏览(34)
  • 【linux】探索Linux命令行中强大的网络工具:netstat

    在Linux命令行中,有许多实用的工具可帮助我们管理和监控网络连接。其中一个最重要的工具就是netstat,它提供了丰富的网络连接和统计信息,帮助我们诊断网络问题并了解系统的网络状态。 在日常的网络管理和故障排除过程中,了解系统的网络连接情况是至关重要的。而在

    2024年02月09日
    浏览(43)
  • 【探索Linux】—— 步步学习强大的命令行工具 P.1(Linux简介)

    目录 前言 一、Linux简介 二、linux的不同发行版本 三、Linux的开源性质 四、Linux的特点  五、Linux代码演示(仅供参考)  总结         前面我们讲了C语言的基础知识,也了解了一些数据结构,并且讲了有关C++的一些知识,也相信大家都掌握的不错,今天博主将会新开一个L

    2024年02月14日
    浏览(29)
  • 【探索Linux】—— 强大的命令行工具 P.5(yum工具、git 命令行提交代码)

    前面我们讲了C语言的基础知识,也了解了一些数据结构,并且讲了有关C++的一些知识,也学习了一些Linux的基本操作,也了解并学习了有关Linux开发工具vim 、gcc/g++ 使用,也相信大家都掌握的不错,今天博主带大家了解一下 —— yum工具以及git 命令行提交代码 , 下面话不多说

    2024年02月12日
    浏览(35)
  • 【探索Linux】—— 强大的命令行工具 P.9(进程地址空间)

    前面我们讲了C语言的基础知识,也了解了一些数据结构,并且讲了有关C++的一些知识,也学习了一些Linux的基本操作,也了解并学习了有关Linux开发工具vim 、gcc/g++ 使用、yum工具以及git 命令行提交代码也相信大家都掌握的不错,上一篇文章我们了解了关于进程的基本概念,今

    2024年02月08日
    浏览(33)
  • 【探索Linux】—— 强大的命令行工具 P.7(进程 · 进程的概念)

    前面我们讲了C语言的基础知识,也了解了一些数据结构,并且讲了有关C++的一些知识,也学习了一些Linux的基本操作,也了解并学习了有关Linux开发工具vim 、gcc/g++ 使用、yum工具以及git 命令行提交代码也相信大家都掌握的不错,今天博主带大家了解一下 —— 进程(进程的概

    2024年02月10日
    浏览(31)
  • 【探索Linux】—— 强大的命令行工具 P.22(POSIX信号量)

    在上一篇文章中,我们深入探讨了多线程编程的核心概念,包括线程同步、条件变量以及线程安全等关键技术,为读者揭示了并发编程的复杂性及其解决方案。这些概念和技术是实现高效、稳定并发应用程序的基础。继续在并发编程的旅途上前进,本篇文章将引导我们走进

    2024年02月20日
    浏览(28)
  • 【探索Linux】—— 强大的命令行工具 P.8(进程优先级、环境变量)

    前面我们讲了C语言的基础知识,也了解了一些数据结构,并且讲了有关C++的一些知识,也学习了一些Linux的基本操作,也了解并学习了有关Linux开发工具vim 、gcc/g++ 使用、yum工具以及git 命令行提交代码也相信大家都掌握的不错,上一篇文章我们了解了关于进程的基本概念,今

    2024年02月09日
    浏览(36)
  • 【探索Linux】—— 强大的命令行工具 P.16(进程信号 —— 信号产生 | 信号发送 | 核心转储)

    在现代社会中,信号无处不在。我们的生活充满了各种各样的信号,它们指引着我们前进的方向,使我们能够了解周围环境的变化。正如在计算机编程中一样,Linux进程信号也是一种重要的信号,它们扮演着相似的角色。 想象一下,在繁忙的城市街道上行驶,交通信号灯是我

    2024年02月05日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包