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

【Linux】IO 篇:文件调用原理,文件描述符,FILE的内涵,解析重定向,理解缓冲区

文章目录

  • 一、系统调用接口
  • 二、文件调用
      • 1. 文件描述符 fd
      • 2. 文件调用原理
      • 3. FILE
  • 三、重定向
      • dup2
  • 四、缓冲区
  • 简易 FILE 的代码实现

文件被加载之前,被存在磁盘上,操作文件,文件的部分内容则会被调度到 内存中。

要分析文件,我们也把文件分成两种:

  • 磁盘上的文件(文件系统)
  • 内存中的文件

这里谈论的是,内存中的文件

文件被打开,OS 会为被打开的文件创建对应的内核数据结构 struct file,将所有这个类型的结构体用某种数据结构链接起来以供 OS 管理。

struct file
{// 各种文件属性(磁盘中读出来的)// 各种链接关系// 缓冲区相关
};

一、系统调用接口


主要介绍一个

open

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>// man 手册查看
man 2 open
  • int open(const char *pathname, int flags)
  • int open(const char *pathname, int flags, mode_t mode);

参数 pathname:

  • 文件名

参数 flags:

  • 标志位,man 2 手册可查

参数 mode:

  • 设置(新建)文件权限

返回值:

  • 为 -1 则说明,open 失败
  • 非负为 文件描述符(见后文)

参数 flags

  • O_CREAT | O_WRONLY
    如果没有文件则创建生成,
    默认不会对原始文件内容做清空,会从从最开始覆盖

  • O_CREAT | O_WRONLY | O_TRUNC
    如果没有文件则创建生成
    清空 写

  • O_CREAT | O_WRONLY | O_APPEND
    如果没有文件则创建生成
    追加写

注意在往文件里写入的时候,strlen(str) 不要 +1,因为 ‘\0’ 是 C 语言的结束规定,不是文件的规定,加进去会乱码。

使用系统接口进行 IO 的时候,一定要注意,\0 问题

我们 C 语言使用的一系列函数

  • fopen、fclose、fwrite/fputs、fread/fgets

都是系统函数的封装

  • open、close、write、read

二、文件调用


1. 文件描述符 fd

任何一个进程,在启动的时候,默认都会打开三个文件:

  • 标准输入 - - 设备文件 -> 键盘文件   0

  • 标准输出 - - 设备文件 -> 显示器文件   1

  • 标准错误 - - 设备文件 -> 显示器文件   2

      其中 标准输出 和 标准错误 都会向 显示器 打印,但他们其实是不一样的。eg:测试中,输入受重定向符的影响,而错误不受重定向符的影响
    

文件描述符,也是 open 对应的返回值。我们创建的文件返回的值是从 3 开始的,而 0 1 2 正是被上面默认打开的三个文件占用了。这个数字本质就是 数组下标

一张简图:
在这里插入图片描述

进程中,文件描述符的分配规则:
在文件描述符表中,最小的,没有被使用的数组元素,分配给新文件
fclose(stdin);
// 等价于
close(0);

2. 文件调用原理

  • 1 个进程 可以调度 n 个文件,每个文件都有 一个缓冲区
  • 调用 read / write / close 这些系统接口时,都需要文件操作符。也就是说,在操作系统层面,我们必须要访问fd,才可以找到文件
  • 我们所谓的 IO 类 read / write 函数,本质上是 拷贝函数
  • 什么时候将缓冲区上的内容刷新到磁盘中指定的位置,由 OS 自主决定
  • 进程 和 文件 并没有深度耦合,便于操作系统的管理
    在这里插入图片描述

如何理解一切皆文件:

  • 每个硬件都有一个 struct file 对象,C语言里面没有成员函数,使用的就是函数指针完成的众多行为。
  • 进程通过 指针数组,访问的其实是这些 struct file 对象,包括里面的缓冲区、函数指针…
  • 而用户的操作,实际上都是进程的操作
  • 所以我们说,Linux 下,一切皆文件
    在这里插入图片描述

3. FILE

#include <stdio.h>
extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;FILE *fopen(const char *path, const char *mode);

在这里插入图片描述

这里的 FILE * 是 结构体类型!由 C语言提供的,跟内核的 struct file 没有任何关系。

我们指定在操作系统层面,我们必须要访问 fd,才可以找到文件。也就是说 struct FILE 里面必定封装了 fd。

我们来看 FILE 源码是这样写的:

typedef struct _IO_FILE FILE;/usr/include/stdio.hstruct _IO_FILE {//...int _fileno; //封装的文件描述符,就是我们说的 fd// C语言维护的缓冲区相关内容//...
};

测试如下:

print("%d\n", stdin->_fileno);
print("%d\n", stdout->_fileno);
print("%d\n", stderr->_fileno);
FILE *fp = fopen("test.txt", "w");
print("%d\n", fp->_fileno);--------
输出结果:
0
1
2
3

三、重定向


🌰< 输出重定向举例

close(1);
int fd = open("test.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);	// fd = 1printf("hello\n"); // stdout -> 1
printf("hello\n");
printf("hello\n");---------
hello
hello
hello
字样,被保存进了 test.txt 中

在这里插入图片描述

🌰> 输入重定向举例

close(0);
int fd = open("test.txt", O_RDONLY);	// fd = 0int a,b;
scanf("%d %d", &a, &b);	// stdin -> 0
printf("a = %d, b = %d\n", a, b);---------
在 test.txt 文件中写入 123 456
运行程序后输出
a = 123, b = 456

在这里插入图片描述

🌰>>追加重定向举例

close(1);
int fd = open("test.txt", O_WRONLY | O_CREAT | O_APPEND, 0666);	// fd = 1printf("hello\n"); // stdout -> 1
printf("hello\n");
printf("hello\n");---------
运行两次则有
hello
hello
hello
hello
hello
hello
字样,被保存进了 test.txt 中

回头看之前的问题

其中 标准输出 和 标准错误 都会向 显示器 打印,但他们其实是不一样的。
eg:测试中,输入受重定向符的影响,而错误不受重定向符的影响

原因如下:

stdout、cout -> 他们都是向 1 号文件描述符对应的文件打印;
stderr、cerr -> 他们都是向 2 号文件描述符对应的文件打印。
输出重定向时,更改的只是 1 号对应的指向,2 号未被影响。

当我们需要手动分离一个程序正确和错误信息的时候:

./a.out 1>log.txt 2>err.txt

当然也有直接的函数可以使用

dup2

头文件:

#include <unistd.h>

int dup2(int oldfd, int newfd);

参数 oldfd:

  • 最后需要的 fd

参数 newfd:

  • 需要被覆盖的 fd

相当于,把本应该到 newfd 上的,重定向到 oldfd,最后剩下的只有 oldfd

四、缓冲区

C 语言维护的 FILE 结构体 和 OS 维护的 struct file 结构体,都有自己的缓冲区(每个对象都有自己的缓冲区),这两个缓冲区是不相同的。

在这里插入图片描述

C库提供的刷新策略,一般有三种:

  1. 无缓冲
  2. 行缓冲(遇到 \n 刷新)
  3. 全缓存(缓冲区满了刷新)
  • 显示器采用的刷新策略:行缓冲
    普通文件采用的刷新策略:全缓冲

缓冲区的作用:节省调用者的时间

这会产生一些奇怪的现象:

// c 库
fprintf(stdout, "hello fprintf\n");
// os 系统调用
const char *msg = "hello write\n";
write(1, msg, strlen(msg));fork();

这个程序我们在 linux 下,重定向到文件,会出现如下情况

[xxx@hostname file]$ ./a.out
hello write
hello fprintf
[xxx@hostname file]$ ./a.out > test.txt
[xxx@hostname file]$ cat test.txt
hello write
hello fprintf
hello fprintf
[xxx@hostname file]$

第一个运行容易理解,分析第二次 cat 文件内容出现的结果
原因如下:

  • 首先,write 正常调用输出到显示器
  • fprintf 的缓冲区,对于重定向到普通文件,使用全缓冲,这里的内容显然不能将缓冲区填满,所以进程结束时刷新
  • 一直到 fork 被调用,程序还没结束,此时父子进程的缓冲区里都有一份 hello fprintf。谁先结束谁就先写诗拷贝,刷新到屏幕上,于是被打了两次

简易 FILE 的代码实现


👉🔗链接如下



🥰如果本文对你有些帮助,请给个赞或收藏,你的支持是对作者大大莫大的鼓励!!(✿◡‿◡) 欢迎评论留言~~


相关文章:

【Linux】IO 篇:文件调用原理,文件描述符,FILE的内涵,解析重定向,理解缓冲区

文章目录 一、系统调用接口二、文件调用1. 文件描述符 fd2. 文件调用原理3. FILE 三、重定向dup2 四、缓冲区简易 FILE 的代码实现 文件被加载之前&#xff0c;被存在磁盘上&#xff0c;操作文件&#xff0c;文件的部分内容则会被调度到 内存中。 要分析文件&#xff0c;我们也…...

力扣:47. 全排列 II(Python3)

题目&#xff1a; 给定一个可包含重复数字的序列 nums &#xff0c;按任意顺序 返回所有不重复的全排列。 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;力扣 示例&#xff1a; 示例 1&#xff1a; 输入&#xff1a;nums [1,1,2] 输出&#xff1a;[…...

Android uart-修改串口节点名

需求: 应客户软件的需求,需要将Android系统里面的/dev/ttyS3节点名称修改为/dev/ttyS9; 实现: 1、判断 driver->name是否为"ttyS",index是否为3,如果是的话替换为ttyS9; diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c old mode 100644 new …...

【HarmonyOS】键盘遮挡输入框时,实现输入框显示在键盘上方

【关键字】 harmonyOS、键盘遮挡input&#xff0c;键盘高度监听 【写在前面】 在使用API6、API7开发HarmonyOS应用时&#xff0c;常出现页面中需要输入input&#xff0c;但是若input位置在页面下方&#xff0c;在input获取焦点的时候&#xff0c;会出现软键盘挡住input情况&a…...

day19-二叉树的最大最小深度

二叉树的最大/最小深度 给定一个二叉树 root &#xff0c;返回其最大/小深度。 二叉树的 最大/小深度 是指从根节点到最远/近叶子节点的最长路径上的节点数。 思路 求最大深度比较简单&#xff0c;我们先解决最大深度。 最大深度 递归 class Solution { public:int maxD…...

Ansible-roles

Ansible-roles 一、roles作用 把playbook剧本里的各个play看作为角色&#xff0c;将各个角色的tasks任务、vars变量、templates模板、files文件等内容放置到角色的目录中统一管理&#xff0c;需要的时候可在playbook中直接使用roles调用&#xff0c;所以roles可以实现playboo…...

NullPointerException导致手机重启案例分析

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 一、 Framework 层对象 空指针导致手机重启。二、解决方案&#xff0c;规避空指针三、Telecom APK 控制导致的重启举例 一、 Framework 层对象 空指针导…...

JAVA 反编译工具

Releases deathmarine/Luyten GitHub 安装exe 打开拖入文件即可...

(AcWing)分组背包问题

有 N 组物品和一个容量是 V 的背包。 每组物品有若干个&#xff0c;同一组内的物品最多只能选一个。 每件物品的体积是 vij&#xff0c;价值是 wij&#xff0c;其中 i 是组号&#xff0c;j 是组内编号。 求解将哪些物品装入背包&#xff0c;可使物品总体积不超过背包容量&…...

JSP项目国际化词条统计

国际化字条匹配并导出为excel格式 需求 将jsp页面里的key值&#xff0c;就是<spring:message code"gsyezer_Single_crystal"/>里的gsyezer_Single_crystal。和对应的字条对应上&#xff0c;并以excel表格形式输出。 jsp页面key值示例 <label for"&…...

Java课题笔记~ MyBatis缓存

为了减少重复查询给数据库带来的压力&#xff0c;MyBatis提供了缓存机制&#xff0c;这种机制能够缓存查询的结果&#xff0c;避免重复的查询。 MyBatis提供了两种缓存方式&#xff1a; 一种为针对于SqlSession的缓存【默认开启】 另一种为针对于全局的缓存【手动开启】 一…...

数据结构--循环队列、链队

基础知识 //循环队列数据结构 typedef struct { QElemType data[MaxQSize];//数据域 int front,rear; //队头队尾指针 }SqQueue; //链队结点数据结构 typedef struct QNode { int data;//数据域 struct QNode* next;//指针域 }QNode, * QueuePtr; typedef struct { struct Q…...

hbuilderx主题色分享-github风格

效果 步骤 hbuilderx总共有三种主题&#xff0c;绿柔主题Default,酷黑主题Monokai,雅黑主题Atom One Dark,修改主题色是基于三种主题之一的&#xff0c;不能直接创建一个新主题&#xff0c;比如下方配置是基于Atom One Dark(对象名为[Atom One Dark])&#xff0c;则当前hbuild…...

【C++】类与对象(1)

文章目录 前言一、什么是类1.类的定义2.类的访问限定符3.类的作用域 二、类的实例化三、类对象的存储方式四、this指针总结 前言 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。C是基于面向对象的&#x…...

Java课题笔记~ MyBatis核心配置

一、核心配置文件概览 MyBatis配置文件中有MyBatis框架的核心配置&#xff0c;负责对MyBatis进行全局管理。它包含许多控制MyBatis功能的重要元素。 <configuration><!--设置配置文件--><properties><property name"" value""/>…...

从0开始自学网络安全(黑客)

前言 黑客技能是一项非常复杂和专业的技能&#xff0c;需要广泛的计算机知识和网络安全知识。你可以参考下面一些学习步骤&#xff0c;系统自学网络安全。 在学习之前&#xff0c;要给自己定一个目标或者思考一下要达到一个什么样的水平&#xff0c;是学完找工作&#xff08;…...

kotlin 编写一个简单的天气预报app(四)增加界面显示

编写界面来显示返回的数据 用户友好性&#xff1a;通过界面设计和用户体验优化&#xff0c;可以使天气信息更易读、易理解和易操作。有效的界面设计可以提高用户满意度并提供更好的交互体验。 增加城市名字的TextView <TextViewandroid:id"id/textViewCityName"…...

英语不好能学好Python吗?Python常用英文单词汇总

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 有些小可爱对英语好不好对学习python有没有什么影响有着很深的疑惑。 其实python学习&#xff0c;主要靠多敲多练&#xff0c;主打一个熟能生巧 那今天我就给大家带来Python常用英文单词汇总&#xff0c; 新手期小可…...

Counting Stars 2023“钉耙编程”中国大学生算法设计超级联赛(5)hdu7335

Problem - 7335 题目大意&#xff1a;如果一个点连接着k个点&#xff0c;就称这k1个点构成k星图&#xff0c;现给出一个大小为n的图&#xff0c;问2星图的数量^3星图的数量^...^n星图的数量是多少 3<n<1e6;1<m<1e6 思路&#xff1a;因为边数总共不超过1e6&#…...

浅谈document.write()输出样式

浅谈document.write()输出样式 js中的最基本的命令之一&#xff1a;document.write&#xff08;&#xff09;&#xff0c;用于简单的打印内容到页面上&#xff0c;可以逐字打印你需要的内容——document.write("content"),这里content就是需要输出的内容&#xff1b;…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

在 Spring Boot 项目里,MYSQL中json类型字段使用

前言&#xff1a; 因为程序特殊需求导致&#xff0c;需要mysql数据库存储json类型数据&#xff0c;因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...

「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案

在移动互联网营销竞争白热化的当下&#xff0c;推客小程序系统凭借其裂变传播、精准营销等特性&#xff0c;成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径&#xff0c;助力开发者打造具有市场竞争力的营销工具。​ 一、系统核心功能架构&…...

什么是VR全景技术

VR全景技术&#xff0c;全称为虚拟现实全景技术&#xff0c;是通过计算机图像模拟生成三维空间中的虚拟世界&#xff0c;使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验&#xff0c;结合图文、3D、音视频等多媒体元素…...

【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验

Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...