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

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

Linux学习笔记:

https://blog.ZEEKLOG.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中,文件描述符被划分为三大类:

标准输入(stdin):文件描述符为0,表示程序的标准输入流,通常指向键盘输入。标准输出(stdout):文件描述符为1,表示程序的标准输出流,通常指向终端。标准错误(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 中的应用场景。希望这些知识对你有所帮助。

本篇笔记:


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

Read more

【AI大模型】DeepSeek + 通义万相高效制作AI视频实战详解

【AI大模型】DeepSeek + 通义万相高效制作AI视频实战详解

目录 一、前言 二、AI视频概述 2.1 什么是AI视频 2.2 AI视频核心特点 2.3 AI视频应用场景 三、通义万相介绍 3.1 通义万相概述 3.1.1 什么是通义万相 3.2 通义万相核心特点 3.3 通义万相技术特点 3.4 通义万相应用场景 四、DeepSeek + 通义万相制作AI视频流程 4.1 DeepSeek + 通义万相制作视频优势 4.1.1 DeepSeek 优势 4.1.2 通义万相视频生成优势 4.2

By Ne0inhk
【DeepSeek微调实践】DeepSeek-R1大模型基于MS-Swift框架部署/推理/微调实践大全

【DeepSeek微调实践】DeepSeek-R1大模型基于MS-Swift框架部署/推理/微调实践大全

系列篇章💥 No.文章01【DeepSeek应用实践】DeepSeek接入Word、WPS方法详解:无需代码,轻松实现智能办公助手功能02【DeepSeek应用实践】通义灵码 + DeepSeek:AI 编程助手的实战指南03【DeepSeek应用实践】Cline集成DeepSeek:开源AI编程助手,终端与Web开发的超强助力04【DeepSeek开发入门】DeepSeek API 开发初体验05【DeepSeek开发入门】DeepSeek API高级开发指南(推理与多轮对话机器人实践)06【DeepSeek开发入门】Function Calling 函数功能应用实战指南07【DeepSeek部署实战】DeepSeek-R1-Distill-Qwen-7B:本地部署与API服务快速上手08【DeepSeek部署实战】DeepSeek-R1-Distill-Qwen-7B:Web聊天机器人部署指南09【DeepSeek部署实战】DeepSeek-R1-Distill-Qwen-7B:基于vLLM 搭建高性能推理服务器10【DeepSeek部署实战】基于Ollama快速部署Dee

By Ne0inhk

DeepSeek各版本说明与优缺点分析_deepseek各版本区别

DeepSeek各版本说明与优缺点分析 DeepSeek是最近人工智能领域备受瞩目的一个语言模型系列,其在不同版本的发布过程中,逐步加强了对多种任务的处理能力。本文将详细介绍DeepSeek的各版本,从版本的发布时间、特点、优势以及不足之处,为广大AI技术爱好者和开发者提供一份参考指南。 1. DeepSeek-V1:起步与编码强劲 DeepSeek-V1是DeepSeek的起步版本,这里不过多赘述,主要分析它的优缺点。 发布时间: 2024年1月 特点: DeepSeek-V1是DeepSeek系列的首个版本,预训练于2TB的标记数据,主打自然语言处理和编码任务。它支持多种编程语言,具有强大的编码能力,适合程序开发人员和技术研究人员使用。 优势: * 强大编码能力:支持多种编程语言,能够理解和生成代码,适合开发者进行自动化代码生成与调试。 * 高上下文窗口:支持高达128K标记的上下文窗口,能够处理较为复杂的文本理解和生成任务。 缺点: * 多模态能力有限:该版本主要集中在文本处理上,缺少对图像、语音等多模态任务的支持。 * 推理能力较弱:尽管在自然语言

By Ne0inhk

用DeepSeek和Cursor从零打造智能代码审查工具:我的AI编程实践

💂 个人网站:【 摸鱼游戏】【神级代码资源网站】【星海网址导航】摸鱼、技术交流群👉 点此查看详情 引言:AI编程革命下的机遇与挑战 GitHub统计显示,使用AI编程工具的开发者平均效率提升55%,但仅有23%的开发者能充分发挥这些工具的潜力。作为一名全栈工程师,我曾对AI编程持怀疑态度,直到一次紧急项目让我彻底改变了看法。客户要求在72小时内交付一个能自动检测代码漏洞、优化性能的智能审查系统,传统开发方式根本不可能完成。正是这次挑战,让我探索出DeepSeek和Cursor这对"黄金组合"的惊人潜力。 一、工具选型:深入比较主流AI编程工具 1.1 为什么最终选择DeepSeek+Cursor? 经过两周的对比测试,我们发现不同工具在代码审查场景的表现差异显著: 工具代码理解深度响应速度定制灵活性多语言支持GitHub Copilot★★★☆★★★★★★☆★★★★Amazon CodeWhisperer★★☆★★★☆★★★★★★☆DeepSeek★★★★☆★★★★★★★☆★★★★☆Cursor★★★☆★★★★☆★★★★★★★★ 关键发现: * Dee

By Ne0inhk