当前位置: 首页 > ops >正文

Linux系统之----重定向

1.文件描述符和文件结构体

前文我们已经了解了文件描述符,回顾一下,文件描述符是一个非负整数,用于标识一个打开的文件。在Linux系统中,文件描述符是一个整数,通常使用int类型来表示。每个进程都有一个文件描述符表(files_struct),用于存储该进程打开的所有文件的描述符。文件描述符表中的每个条目都指向一个struct file结构体,该结构体包含了文件的详细信息。

现在我们在介绍一下struct file

struct file是一个结构体,用于描述一个打开的文件。它包含了文件的各种信息,如文件类型(标准输入、标准输出、标准错误或普通文件)、文件偏移量等。struct file中有一个指针f_inode,指向文件的inode结构体,inode包含了文件的元数据(如文件大小、权限等)。

最终我们总结一下文件操作,在Linux系统中,所有文件操作(如读写)都是通过文件描述符进行的。操作系统通过文件描述符来识别和管理文件。

2.文件读写操作

2.1 文件读写的本质

文件读写操作实际上是对文件内核缓冲区的操作。内核缓冲区是操作系统为文件分配的内存区域,用于暂存文件数据。readwrite函数并不是直接对磁盘文件进行操作,而是对文件内核缓冲区进行操作。所以,write根本就不是写入到文件,wite本质是拷贝函数!把数据从用户空间拷贝到对应文件的内核缓冲区中!不仅仅是写,我们进行的任何文件内容的增删查改,都必须把文件的内容提前预加载到该文件的文件内核缓冲区中!

2.2 文件内容和属性

文件由内容和属性组成。内容是文件的实际数据,属性包括文件的大小、权限等元数据。文件内核缓冲区中保存了文件的内容,而文件属性则保存在磁盘上的文件系统中。

2.3 文件操作的内部机制

当我们对文件进行读写操作时,实际上是在操作文件内核缓冲区。操作系统会在适当的时候将缓冲区中的数据写入磁盘,而什么时候写入到磁盘文件,由OS自己决定时机来进行刷新。文件描述符表中的struct file结构体包含了文件的内核缓冲区信息,通过这些信息,操作系统可以管理和操作文件。

附上老师的板书:

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

我们先看几组代码

代码组1:

#include <stdio.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
int main() 
{ int fd = open("myfile", O_RDONLY); if(fd < 0){ perror("open"); return 1; } printf("fd: %d\n", fd); close(fd); return 0; 
}

运行并执行,发现结果直接是3 

代码组2:

#include <stdio.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
int main() 
{ close(2);int fd = open("myfile", O_RDONLY); if(fd < 0){ perror("open"); return 1; } printf("fd: %d\n", fd); close(fd); return 0; 
}

当我们关掉文件操作符号2时,发现fd的文件操作符变为了2 

 

代码组3:

#include <stdio.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
int main() 
{ close(0);int fd = open("myfile", O_RDONLY); if(fd < 0){ perror("open"); return 1; } printf("fd: %d\n", fd); close(fd); return 0; 
}

 当我们关掉文件操作符号0时,发现fd的文件操作符变为了0 

 

由此,我们可以推断出在files_struct数组当中,找到当前没有被使⽤的最小的一个下标,作为新的文件描述符。

4.重定向

上述例子中,倘若我要是close(1)呢?我们试一下

惊奇的发现没有结果输出了,原因就是1所对应的是stdout,stdout是向屏幕显示器文件输出,你给他关了他往哪输出去? 但是我们真的查看不到了吗?实际上结果被写到了myfile文件里面,不信自己试一下:

也就是说,本来应该输出到显示器上的内容,输出到了文件  myfile 当中,其中,fd=1。这
种现象叫做输出重定向。常见的重定向有: > , >> , <
不理解的可以看一下这个图:

那么,重定向本质是什么?

4.1 重定向本质 

重定向的本质是改变进程的标准输入(stdin)、标准输出(stdout)和标准错误(stderr)的默认流向。在Unix/Linux系统中,默认情况下,这些流分别对应终端输入、终端显示和终端错误显示。通过重定向我们可以将这些流改向到文件或其他命令,从而实现数据的灵活处理和错误信息的记录。

4.1.2 dup2

我们先查一下他

出来一堆乱糟糟的东西看不懂思密达。。。。。 

好下面是对其的解释:

说人话就是: 

dup2 是一个在 Unix 和 Linux 系统中用于复制文件描述符的系统调用。它的作用是将一个已经打开的文件描述符复制到另一个文件描述符上,同时可以选择性地关闭目标文件描述符上原有的文件。

参数说明:

oldfd:要复制的原始文件描述符。

newfd:目标文件描述符。如果该文件描述符已经打开,它会被关闭,然后被复制。

返回值

成功时返回新的文件描述符(通常与 newfd 相同)。失败时返回 -1,并设置 errno 以指示错误原因。

代码示例:

在示例之前,我们先看一个函数read,生词挺少的这里我就不翻译了~!

#include <stdio.h> 
#include <unistd.h> 
#include <fcntl.h> 
int main() 
{ int fd = open("./log", O_CREAT | O_RDWR); if (fd < 0){ perror("open"); return 1; } close(1); dup2(fd, 1);for (;;) { char buf[1024] = {0}; ssize_t read_size = read(0, buf, sizeof(buf) - 1); if (read_size < 0) { perror("read"); break; }printf("%s", buf); fflush(stdout); }return 0; 
}

 

 本篇文章到此为止!!

http://www.xdnf.cn/news/6931.html

相关文章:

  • 基于OpenCV的SIFT特征和FLANN匹配器的指纹认证
  • 泛微对接金蝶云星空实战案例技术分享
  • C++:C++内存管理
  • DeerFlow试用
  • 一周学会Pandas2 Python数据处理与分析-Pandas2数据添加修改删除操作
  • 使用python进行人员轨迹跟踪
  • 打造动效按钮平台 ButtonCraft:我和 CodeBuddy 的协作旅程
  • Nginx应用场景详解与配置指南
  • 源码安装gperftools工具
  • AI Agent | Coze 插件使用指南:从功能解析到实操步骤
  • 湖北理元理律师事务所:债务优化中的双维支持实践解析
  • 【HCIA】聚合VLAN
  • 蓝牙HFP协议概述
  • 开源项目实战学习之YOLO11:12.1 ultralytics-models-sam-blocks.py源码
  • 【Spring】Spring的请求处理
  • Spring-boot初次使用
  • 2.单链表两数相加(java)
  • 记录算法笔记(2025.5.17)验证二叉搜索树
  • 题单:表达式求值1
  • LVGL- Calendar 日历控件
  • [YOLO模型](4)YOLO V3的介绍
  • 基于STM32_HAL库的SPI通信并驱动W25Q64存储模块
  • RK3588 MNN CPU/Vulkan/OpenCL ResNet50推理测试
  • FreeRTOS的学习记录(任务创建,任务挂起)
  • 【数据结构】_二叉树
  • MyBatis 核心组件源码分析
  • JS逆向-某易云音乐下载器
  • 安卓 Audio Stream 类型
  • 【找工作系列①】【大四毕业】【复习】巩固JavaScript,了解ES6。
  • 复旦微FMQL调试笔记:PS网口