首页 > 系统相关 >【Linux探索学习】第二十一弹——文件描述符和输出重定向:深入解析Linux操作系统中的文件描述符与输出重定向的底层机制

【Linux探索学习】第二十一弹——文件描述符和输出重定向:深入解析Linux操作系统中的文件描述符与输出重定向的底层机制

时间:2024-12-12 22:59:23浏览次数:5  
标签:文件 txt 重定向 输出 描述符 Linux include

Linux学习笔记:

https://blog.csdn.net/2301_80220607/category_12805278.html?spm=1001.2014.3001.5482

前言:

在上一篇,我们已经讲解过文件描述符的相关问题了,但是今天,由于讲解重定向问题需要更进一步理解文件描述符的问题,所以我们先对文件描述符的问题进行一些补充讲解,然后再重点讲解一下重定向的问题。

目录

一、文件描述符

1.1 文件描述符的类型

1.2 文件描述符的管理

1.3 文件描述符的相关操作

二、输出重定向

2.1 基本的重定向

2.2 重定向标准错误输出

2.3 同时重定向标准输出和标准错误输出

2.4 输入输出重定向与管道

三、文件描述符和输出重定向的结合

3.1 重定向的本质

3.2 dup2系统调用来实现重定向

3.3 其它

四、总结


一、文件描述符

我们还是先再来讲解一遍文件描述符:在Linux中,每个打开的文件都会被分配一个文件描述符。文件描述符是一个非负整数,操作系统内核通过它来跟踪进程与文件之间的关联。文件描述符提供了与文件进行交互的通道,可以通过它执行各种文件操作。

1.1 文件描述符的类型

在Linux中,文件描述符被划分为三大类:

  1. 标准输入(stdin):文件描述符为0,表示程序的标准输入流,通常指向键盘输入。
  2. 标准输出(stdout):文件描述符为1,表示程序的标准输出流,通常指向终端。
  3. 标准错误(stderr):文件描述符为2,表示程序的标准错误流,也指向终端,通常用于输出错误信息。

除了这三个标准流,Linux允许通过系统调用打开其他文件或设备,从而获得新的文件描述符。这些文件描述符可以通过文件I/O操作进行读写。

1.2 文件描述符的管理

文件描述符是由操作系统内核管理的,它们与一个实际的文件表项(文件描述符表)相对应。每个进程都有一个与之关联的文件描述符表,用于记录当前进程打开的所有文件和设备的信息。

同时每个文件描述符也对应着一个描述该文件的内容及属性的结构体对象,这就是操作系统管理文件的本质

文件描述符类型描述
0stdin标准输入流
1stdout标准输出流
2stderr标准错误流
3+普通文件可通过系统调用open()获取的文件描述符

通过调用open()系统调用,我们可以打开一个文件并获取其对应的文件描述符。open()函数的基本原型如下:

int open(const char *pathname, int flags, mode_t mode);
  • pathname:文件路径。
  • flags:打开文件时的标志,例如O_RDONLY(只读)、O_WRONLY(只写)、O_RDWR(读写)等。
  • mode:文件权限,仅在创建文件时使用。

打开文件后,操作系统会返回一个文件描述符,用于后续的文件操作。

1.3 文件描述符的相关操作

在Linux中,文件描述符常用的操作包括:

  • 读取文件:通过read()系统调用读取文件内容。
  • 写入文件:通过write()系统调用将数据写入文件。
  • 关闭文件:通过close()系统调用关闭文件描述符。

这些系统调用接口我们在上一篇做过详细讲解了,这里就不再介绍了

二、输出重定向

输出重定向是将命令的标准输出(stdout)或者标准错误输出(stderr)重定向到文件、设备或其他进程的一个过程。Linux 提供了非常灵活的方式来实现输出重定向。首先我们先来看基本的重定向,也就是在命令行中可以直接实现的重定向

2.1 基本的重定向

在 Linux 中,我们可以使用 >>> 来将输出重定向到文件。

  • >:将输出重定向到文件,如果文件已存在则覆盖。
  • >>:将输出重定向到文件,如果文件已存在则追加。

例如,执行以下命令时:

echo "Hello, World!" > output.txt

这将把字符串 "Hello, World!" 写入到 output.txt 文件中。如果文件已存在,内容将被覆盖。如果文件还没被创建,则会自动创建并写入

2.2 重定向标准错误输出

除了标准输出,还可以将标准错误输出(stderr)重定向到文件:

echo "An error occurred" 2> error.txt

这将把标准错误输出写入到 error.txt 文件。

2.3 同时重定向标准输出和标准错误输出

有时,我们希望将标准输出和标准错误输出都重定向到同一个文件:

echo "This is normal" > output.txt echo "This is an error" 2>> output.txt

上面的命令中,标准输出被重定向到 output.txt 文件中,而标准错误输出则追加到文件末尾。

2.4 输入输出重定向与管道

重定向不仅仅用于输出,还可以用于输入。例如,我们可以使用 < 来将文件内容作为输入:

cat < input.txt

而管道(|)则可以将一个命令的输出作为另一个命令的输入:

ls | grep "example"

这将列出当前目录下所有文件,并通过管道将输出传递给 grep,过滤出包含 "example" 的文件名。

三、文件描述符和输出重定向的结合

上面我们所讲的输出重定向还都是最基本的输出重定向,是直接在命令行上就能实现的,下面我们来几个文件描述符的在输出重定向中的高级用法

3.1 重定向的本质

首先我们可以结合文件描述符来讲解一下输出重定向在底层中是如何进行的

首先我们先来看这样一段代码:

#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)    //因为文件描述符是数组的下标,所以不可能小于0,小于0就是失败
    {
        perror("open file");
        return 1;
    }
    printf("fd: %d\n",fd);
    const char *msg="hello Linux\n";
    int cnt=5;
    while(cnt)
    {
        write(1,msg,strlen(msg));
        cnt--;
    }
    close(fd);
    return 0
}
   

运行结果:

我们将第一行的注释放开,也就是说关闭1号文件再次执行:

#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)    //因为文件描述符是数组的下标,所以不可能小于0,小于0就是失败
    {
        perror("open file");
        return 1;
    }
    printf("fd: %d\n",fd);
    const char *msg="hello Linux\n";
    int cnt=5;
    while(cnt)
    {
        write(1,msg,strlen(msg));
        cnt--;
    }
    close(fd);
    return 0
}

运行结果:

我们比较一下上面的两段代码和输出结果:

我们可以观察到上面这两段代码唯一的区别就是一个事先把1号文件关闭了,但是它们的输出结果却有很大不同,我们的代码执行的目的就是在屏幕上打印log.txt文件的描述符,并把预期内容写入一号文件中去,而前三号文件我们在前面也讲过是我们在启动进程时是会默认创建的文件,1号文件就是显示器文件,所以第一段代码的打印结果就是直接在屏幕上输出所有打印内容,log.txt的文件标识符则为3(0,1,2被占用),而在第二段代码中,我们首先先将1号文件关闭掉,此时数组中1号文件的对应位置就是空了,此时我们在创建log.txt文件时按从小往大的顺序,就会先找到1号文件,因为1号显示器文件已经被关闭,所以往屏幕上输出内容的操作不能奏效了,而且内容也被写入在log.txt中

所以说重定向的原理就是文件描述符指向的内容的修改(个人理解)

3.2 dup2系统调用来实现重定向

首先我们先来通过man手册来看一下dup2的基本用法

man dup

我们可以看到关于dup的系统调用接口有两个,我们需要掌握的主要是第二个

我们上面的那种重定向的方法使用起来是比较繁琐的,我们必须先关闭1号文件,然后再打开新文件时才能成功,其实也可以通过dup2系统调用的方法直接实现上面的结果

来看看上面同样的代码我们如何用dup2来实现:

#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()                                                                                                                                                                                                   
{
    int fd=open(filename,O_CREAT|O_WRONLY|O_TRUNC,0666);
    if(fd<0)    //因为文件描述符是数组的下标,所以不可能小于0,小于0就是失败
    {
        perror("open file");
        return 1;
    }
    //重定向
    dup2(fd,1);
    printf("fd: %d\n",fd);
    const char *msg="hello Linux\n";
    int cnt=5;
    while(cnt)
    {
        write(1,msg,strlen(msg));
        cnt--;
    }
    close(fd);
    return 0
}

运行结果:

3.3 其它

上面我们就讲解了输出重定向的主要使用方式,除此之外,输出重定向还可以用在几个更高级的场景,比如后台运行与输出重定向和输出重定向和多重文件描述符等,这些内容都属于拔高内容了,等我们学到后面用到的时候再讲

四、总结

文件描述符和输出重定向是 Linux 操作系统中两个非常重要的机制,它们在系统 I/O 操作、进程管理和文件系统中扮演着至关重要的角色。通过深入理解文件描述符的底层实现、相关的系统调用以及输出重定向的工作原理,我们可以更高效地与操作系统交互,了解进程之间交互的本质。

本文详细介绍了文件描述符和输出重定向的基础知识、底层实现、系统调用以及它们在 Linux 中的应用场景。希望这些知识对你有所帮助。

本篇笔记:


感谢各位大佬观看,创作不易,还请各位大佬点赞支持!!!

标签:文件,txt,重定向,输出,描述符,Linux,include
From: https://blog.csdn.net/2301_80220607/article/details/144435657

相关文章

  • 11 UFS 4.0 UFS描述符、标志和属性
    14UFS描述符、标志和属性14.1UFS描述符描述符是一种具  有定义格式的数据结构。描述符通过QUERYREQUESTUPIU数据包进行访问。描述符是独立可寻址的数据结构。描述符可以是每个设备独立存在且唯一的,也可以通过顶级描述符中定义的参数以层次化方式与其他描述符相互关联......
  • Linux:lvm扩容 / 目录(根目录)
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档1.检查当前磁盘使用情况使用 df-h 命令查看当前磁盘使用情况,确认根目录的分区和使用情况。[root@nz~]#df-h文件系统容量已用可用已用%挂载点devtmpfs979M......
  • Linux驱动开发之块设备驱动
    目录Linux块设备子系统块设备驱动初始化请求队列删除请求队列请求块IO(bio)实验程序编写运行测试在Linux的设备驱动架构中,块设备是与字符型设备不同类型的另一种设备,因此内核在支持块设备驱动程序时所使用的相关数据结构和I/O模型的设计等方面都与字符型设备驱动程序......
  • linux下pgrep实现精确查询
    在Linux中,pgrep 是一个命令行工具,用于根据进程名称和其他属性搜索进程。要实现精确查询,您可以使用一些选项来控制搜索行为,以便更准确地匹配进程。使用 pgrep 进行精确查询按进程名完全匹配:使用 -x 选项可以确保只匹配完全的进程名称。例如,若您要查找名为"my_process"......
  • linux下pkill和kill的区别,pkill是模糊查询(危险)
    `pkill`和`kill`是UNIX/Linux系统中用于终止进程的命令,但它们的工作方式有所不同:1.`kill`命令:-`kill`通常用于向一个特定的进程ID(PID)发送信号。默认情况下,它发送的是TERM信号(15),请求进程正常终止。-使用`kill`需要知道确切的PID。你可以通过`ps`,`pgr......
  • 带你从入门到精通——Linux(三. 用户和文件权限)
    建议先阅读我之前的博客,掌握一定的Linux前置知识后再阅读本文,链接如下:带你从入门到精通——Linux(一.基础知识)-CSDN博客带你从入门到精通——Linux(二.扩展知识)-CSDN博客目录三.用户和权限3.1用户操作3.1.1添加用户和删除用户3.1.2切换用户3.1.3用户授权3.2用......
  • 腾讯通RTX升级方案,解决不兼容Linux系统及移动端的问题
    一、腾讯通RTX继续使用面临的主要难题随着腾讯通RTX停止更新并下架官网,用户失去了官方支持和资源下载,同时还暴露出以下无法克服的局限性:●不兼容国产系统与移动端:腾讯通RTX仅支持Windows和Mac系统,无法在基于Linux内核的国产操作系统(如银河麒麟、统信UOS)以及移动设备上正常运行......
  • vscode+wsl Windows和Linux之间的文件同步
    vscode+wslWindows和Linux之间的文件同步创建VSCode任务配置文件运行任务创建VSCode任务配置文件在项目目录下创建或编辑.vscode/tasks.json配置文件//tasks.json{"version":"2.0.0","tasks":[{"label":"SyncWSLtoWindows",......
  • Nexpose 7.1.0 for Linux & Windows - 漏洞扫描
    Nexpose7.1.0forLinux&Windows-漏洞扫描Rapid7on-premVulnerabilityManagement,releasedDec11,2024请访问原文链接:https://sysin.org/blog/nexpose-7/查看最新版。原创作品,转载请保留出处。作者主页:sysin.orgNexposeVulnerabilityScanner您的本地漏洞扫描......
  • Linux中利用find命令查找包含对应字符串的文件
    在Linux中,find命令通常用于查找文件系统中的文件和目录,而不是直接用于查找文本中的字符串。如果您想要在一组文件中查找包含特定字符串的文件,您可以结合使用find命令和grep命令来实现。以下是一些使用find和grep组合来查找包含特定字符串的文件的例子:在当前目录及子目录中查找......