【Linux】简单模拟C语言文件标准库FILE

在这里插入图片描述

👦个人主页:Weraphael
✍🏻作者简介:目前正在学习c++和算法
✈️专栏:Linux
🐋 希望大家多多支持,咱一起进步!😁
如果文章有啥瑕疵,希望大佬指点一二
如果文章对你有帮助的话
欢迎 评论💬 点赞👍🏻 收藏 📂 加关注😍


目录

  • 前言
  • 一、FILE结构体设计
  • 二、fopen函数
  • 二、fwrite函数
  • 三、fflush函数
  • 四、fclose函数
  • 五、总结及相关代码

前言

在这里插入图片描述

在C语言中,FILE结构体一定封装了诸如文件描述符等字段,使得C语言文件操作的库函数可以很好的调用系统调用,因此程序员可以更加方便地使用高级接口来完成任务,而无需深入了解底层系统调用的实现细节。

这篇博客将带领大家深刻理解C语言文件操作函数底层是如何封装系统调用接口,以及C语言用户级缓冲区的现象。

注:本篇博客不是为了造一个更好的轮子,而是重在理解!!!

一、FILE结构体设计

在这里插入图片描述

(以上是库封装的FILE相关字段)

我们知道,C语言的文件操作函数底层必定会调用系统调用接口,而在往期博客中我们知道,文件相关的系统调用接口都是由文件描述符来定位文件的,因此,FILE结构体必定封装了文件描述符。

而我们这篇博客还要实现缓冲区现象,因此,FILE结构体还会封装维护缓冲区的相关字段。

在这里插入图片描述

  • _fileno:文件描述符。
  • outbuffer:输出缓冲区。需要注意的是,用户级缓冲区通常是通过动态内存分配函数(如mallocnew)在堆区分配的,大小是不固定的。
  • out_pos:当前缓冲区字符的个数。

二、fopen函数

C语言中文件打开操作fopen底层调用了系统调用接口open

在这里插入图片描述

open函数的更多详细用法请查看此篇博客:点击跳转

// fopen函数模型
FILE *fopen(const char *path, const char *mode);
// path: 文件的路径
// mode: 文件的打开方式

文件打开的方式mode有很多种,大家可以通过man手册查询,这里我重点实现以下常见的三种:

  • "w": 以只写的方式打开方式。文件不存在会自动创建,并且每打开一次都会将文件内容清空再写入。

  • "a": 以追加的方式打开文件。文件不存在会自动创建,不会对文件原有的内容做清空,而是追加写入。

  • "r": 以只读的方式打开文件,文件不存在会报错。

此外,当使用fopen函数打开文件,对于普通文件,默认情况下会使用全缓冲来刷新缓冲区,即直到缓冲区满了或者遇到'\n'才将缓冲区中的内容写入磁盘。

在这里插入图片描述

二、fwrite函数

C语言中文件写入操作fwrite底层也调用了系统调用接口write

在这里插入图片描述

write函数的更多详细用法请查看此篇博客:点击跳转

// fwrite函数模型
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
  • ptr:指向要写入的数据块的指针。通常使用void*类型的指针,可以传递任何类型的数据块。需要注意的是,ptr指向的数据必须与sizenmemb参数相对应,即size * nmemb表示要写入的总字节数。

  • size:要写入每个数据块的字节数。

  • nmemb:要写入的数据块的数量。表示要写入多少个数据块。

  • stream:指向要写入的文件的指针。需要使用标准库函数fopen()成功打开文件后,将返回的文件指针作为参数传递给fwrite()函数。

  • nmemb值充当返回值。

在这里插入图片描述

用户调用fwrite时,并不会直接将内容直接写入文件中,而是将数据写入到用户级缓冲区,然后通过一定条件,再将缓冲区的内容写入到文件中。详细步骤如下:

  1. 判断当前用户级缓冲区是否被填满。如果满了,先对缓冲区刷新,再进行后续操作。
  2. 如果遇到'\n',就将'\n'之间的字符全部刷新。
  3. 若不满足条件继续将字符往缓冲区里塞。

在这里插入图片描述

三、fflush函数

当用户调用fflush函数时,不管缓冲区是否满了还是什么,直接刷新。因此,fflush函数一定封装了系统调用接口write

// fflush函数原型
int fflush(FILE *stream);

在这里插入图片描述

四、fclose函数

fclose()函数是C语言标准库中用于关闭文件流的函数。它的作用是将缓冲区中剩余的数据写入到文件中,并释放系统资源。因此它的底层必定会调用fflush函数以及系统调用close()

int close(int fd);

在这里插入图片描述

五、总结及相关代码

  • 数据到达文件一共要执行3次拷贝,第一次是拷贝到用户级缓冲区、第二次是拷贝到系统级缓冲区、最后一次则是真正写入文件中(第二次到第三次是由操作系统帮我们完成的)。

  • 在模拟实现fwrite时,我们将一个字符一个字符拷贝到缓冲区,不满足条件,如缓冲区没有满或者没有遇到'\n'就继续拷贝至缓冲区,这不是变相减少了调用系统调用的次数,从而提高IO效率!

本篇博客相关代码:点击跳转

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/15169.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kaggle——First Machine Learning Model

kaggle(需要魔法才能访问):https://www.kaggle.com/ 需要下载的数据集:melb_data.csv、train.csv(已放在资源里面) First Machine Learning Model Selecting Data for Modeling #Selecting Data for Modeling import…

C++ 学习 关于引用

🙋本文主要讲讲C的引用 是基础入门篇~ 本文是阅读C Primer 第五版的笔记 🌈 关于引用 几个比较重要的点 🌿引用相当于为一个已经存在的对象所起的另外一个名字 🌞 定义引用时,程序把引用和它的初始值绑定(b…

【MySQL精通之路】InnoDB磁盘I/O和文件空间管理(11)

主博客: 【MySQL精通之路】InnoDB存储引擎-CSDN博客 目录 1.InnoDB磁盘I/O 1.1 预读 1.2 双写缓冲区 2.文件空间管理 2.1 Pages, Extents, Segments, and Tablespaces(很重要) 2.2 配置保留文件段页面的百分比 2.3 页与表行的关系 …

R可视化:可发表的Y轴截断图

Y轴截断图by ggprism Y轴截断图by ggprism 介绍 ggplot2绘制Y轴截断图by ggprism加载R包 knitr::opts_chunk$set(message = FALSE, warning = FALSE)library(tidyverse) library(ggprism) library(patchwork)rm(list = ls()) options(stringsAsFactors = F) options(future.…

2024年高考考务人员网上培训参考答案

第1部分:单选题 1. 关于试卷保密室负责人职责,以下说法不正确的是(B) [2分] A. 负责试卷的接收、保管和发放工作 B. 试卷保密室内屋门锁钥匙和铁柜门锁钥匙必须由同一人保管 C. 试卷接收和发放应当当面清点试卷袋数量&#…

Go语言的中间件(middleware)是如何实现的?

文章目录 Go语言的中间件(Middleware)是如何实现的?中间件的工作原理中间件的实现步骤示例代码总结 Go语言的中间件(Middleware)是如何实现的? 在Go语言中,中间件(Middleware&#…

springboot实现多开发环境匹配置(超级简洁没废话)

首先logbok-spring.xml里面的内容 <?xml version"1.0" encoding"UTF-8"?> <configuration><!-- 开发、测试环境 --><springProfile name"dev,test"><include resource"org/springframework/boot/logging/log…

探索现代AI生成模型的底层原理:大语言模型、视频模型与图片模型

探索现代AI生成模型的底层原理&#xff1a;大语言模型、视频模型与图片模型 引言大语言模型&#xff08;Large Language Models&#xff09;底层原理先进的模型实例应用与影响挑战与未来发展 视频生成模型底层原理先进的模型实例应用与影响挑战与未来发展 图片生成模型底层原理…

Java并发面试题,多线程通关秘籍

【知识点记录】- 不能不知道的知识点 &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f3c6; 博客首页 怒放吧德德 To记录领地 &#x1f31d;分享学习心得&#xf…

算法设计与分析

一、分治法 二、回溯法 三、贪心法 四、动态规划法 分治法一分而治之 对于一个规模为n的问题&#xff0c;若该问题可以容易地解决&#xff08;比如说规模n较小&#xff09;则直接解决&#xff0c;否则将其分解为k个规模较小的子问题&#xff0c;这些子问题互相独立且与原问题形…

封装UUID

目录 1、 * 封装UUID 1.1、 * 从一个 UU64 恢复回一个 UUID 对象 1.2、 * 64进制表示的 UUID, 内容为 [\\-0-9a-zA-Z_] 1.3、 * 将紧凑格式的 UU16 字符串变成标准 UUID 格式的字符串 package com.my.blog.website.utils;

【数据结构与算法 | 基础篇】单向链表模拟栈

1. 前言 前文我们先后用单向循环链表&#xff0c;环形数组来模拟了队列. 队列的特点是先进先出. 队头移除元素&#xff0c;队尾添加元素. 所以需要两个指针控制.本文我们接下来提及如果和单向链表来模拟栈. 栈的特点是后进先出. 在栈顶压栈或弹栈. 另一侧不动的是栈底. 我们可…

range for

1. 基于范围的for循环语法 C11标准引入了基于范围的for循环特性&#xff0c;该特性隐藏了迭代器 的初始化和更新过程&#xff0c;让程序员只需要关心遍历对象本身&#xff0c;其语法也 比传统for循环简洁很多&#xff1a; for ( range_declaration : range_expression ) {loo…

基于SpringBoot设计模式之结构型设计模式

文章目录 介绍开始 介绍 结构型模式涉及到如何组合类和对象以获得更大的结构。结构型类模式采用继承机制来组合接口或实现。一个简单的例子是采用多重继承方法将两个以上的类组合成一个类&#xff0c;结果这个类包含了所有父类的性质。这一模式尤其有助于多个独立开发的类库协同…

【Linux】关于获取进程退出状态中的core dump标志补充

通过 wait/waitpid 可以获取子进程的退出状态, 从而判断其退出结果. 记录退出状态的 int 变量 status 的使用情况如下图所示: 如果是收到信号终止的话, 低 7 位为收到的终止信号, 而低第 8 位为 core dump 标志, core dump 标志有什么用呢? core dump 标志只存 0/1, 表示是否…

printf 模仿slf4j 的log.xxx效果

printf 模仿slf4j 的log.xxx效果 简介期待的效果颜色遇到的问题实际的效果代码实现使用效果图 简介 突然想玩一玩&#xff0c;能不能用printf实现slf4j里 的log.xxx 的效果。 性能是完全不考虑的&#xff0c;只要功能可用就好。 期待的效果 类似:info("这是第{}条日志…

ffmpeg-webrtc(metartc)给ffmpeg添加webrtc协议

这个是使用metrtc的库为ffmpeg添加webrtc传输协议&#xff0c;目前国内还有一个这样的开源项目&#xff0c;是杨成立大佬&#xff0c;大师兄他们在做&#xff0c;不过wili页面维护的不好&#xff0c;新手不知道如何使用&#xff0c;我专门对它做过介绍&#xff0c;另一篇博文&a…

不同类型水表计量技术的优缺点

1.单流束水表 1.1优点 (1)耐受悬浮固体。适用于硬水或悬浮颗粒物。 (2)多样性&#xff0c;可用性&#xff0c;容易找到需要的合适的表型。 (3)技术可靠&#xff0c;已使用了数十年。 (4)体积小&#xff0c;可以安装在狭小的空间里。 (5)13mm、15mm、20mm水表可能是市面…

CTFHUB技能树——SSRF(二)

目录 上传文件 ​FastCGI协议 Redis协议 上传文件 题目描述&#xff1a;这次需要上传一个文件到flag.php了.祝你好运 index.php与上题一样&#xff0c;使用POST请求的方法向flag.php传递参数 //flag.php页面源码 <?phperror_reporting(0);if($_SERVER["REMOTE_ADDR&…

Java面向对象程序设计-集合容器(toString方法)

以下是翁恺老师3.3.1集合容器的示范代码&#xff1a; class Value{ private int i; public void set(int i){this.ii;}public int get(){return i;}public String toString(){return ""i; } //注意这句的有无 }public class NoteBook {public static void ma…