【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,一经查实,立即删除!

相关文章

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.…

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…

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

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

算法设计与分析

一、分治法 二、回溯法 三、贪心法 四、动态规划法 分治法一分而治之 对于一个规模为n的问题&#xff0c;若该问题可以容易地解决&#xff08;比如说规模n较小&#xff09;则直接解决&#xff0c;否则将其分解为k个规模较小的子问题&#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&…

C语言:有两个磁盘文件A和B,各存放一行字母,要求把这两个文件中的信息合并(按字母顺序排列),输出到一个新文件C中

int main() {int i, j 0;char arr_pfa[100], arr_pfb[100];FILE* pfa fopen("A.txt", "r");//自己事先创建 我这里A存放的是helloif (pfa NULL){perror("error:");return 1;}fgets(arr_pfa, 100, pfa);fclose(pfa);FILE* pfb fopen("B.…

【数据结构】神奇的二叉树

文章目录 前言1. 树形结构1.1 什么是树1.2 名词概念1.3 树的表现形式 2. 二叉树2.1 概念2.2 两种特殊的二叉树2.3 二叉树的性质 3. 二叉树的存储结构3.1 顺序存储3.2 链式存储 4. 二叉树的遍历4.1 前序遍历4.2 中序遍历4.3 后序遍历4.4 层序遍历 5. 遍历的代码实现5.1 递归实现…

PTT票据传递攻击

一. PTT票据传递攻击原理 1.PTT介绍 PTT(Pass The Ticket)&#xff0c;中文叫票据传递攻击&#xff0c;PTT 攻击只能用于kerberos认证中,NTLM认证中没有&#xff0c; PTT是通过票据进行认证的。 进行票据传递&#xff0c;不需要提权&#xff0c;域用户或者system用户就可以 …

【图书推荐】《Vue.js 3.x+Element Plus从入门到精通(视频教学版)》

本书用处 内容简介 本书通过对Vue.js&#xff08;简称Vue&#xff09;的示例和综合案例的介绍与演练&#xff0c;使读者快速掌握Vue.js 3.x框架的用法&#xff0c;提高Web前端的实战开发能力。本书配套示例源码、PPT课件、教学大纲、教案、同步教学视频、习题及答案、其他资源…

HTML+CSS 响应式导航栏

效果演示 Code <div class="navbar"><input type="checkbox"><span></span><span></span><ul><li><a href="#">点赞</a></li><li><a href="#">关注&…

SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?

尼恩&#xff1a;LLM大模型学习圣经PDF的起源 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;经常性的指导小伙伴们改造简历。 经过尼恩的改造之后&#xff0c;很多小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试机会&#x…

【数据结构】数据结构中的隐藏玩法——栈与队列

前言&#xff1a; 哈喽大家好&#xff0c;我是野生的编程萌新&#xff0c;首先感谢大家的观看。数据结构的学习者大多有这样的想法&#xff1a;数据结构很重要&#xff0c;一定要学好&#xff0c;但数据结构比较抽象&#xff0c;有些算法理解起来很困难&#xff0c;学的很累。我…

前端基于word模板导出word文档

项目环境 vue2 js vue-cli等 依赖包都可以在npm官网找到对应文档 npm官网(英文) 1、依赖 安装依赖 docxtemplater npm i docxtemplaterfile-saver npm i file-saverjszip-utils npm i jszip-utilsjszip npm i jszip在对应页面或模块中引入依赖 import Docxtemplater …

QQ个性网空间日志网站模板源码

QQ个性网空间日志网站模板源码自带后台登录设置&#xff0c;适用于博客、文章、资讯、其他类网站内容使用。模板自带eyoucms内核&#xff0c;原创设计、手工书写DIVCSS&#xff0c;完美兼容IE7、Firefox、Chrome、360浏览器等;主流浏览器;结构容易优化;多终端均可正常预览。由于…

力扣刷题---2206. 将数组划分成相等数对【简单】

题目描述&#x1f357; 给你一个整数数组 nums &#xff0c;它包含 2 * n 个整数。 你需要将 nums 划分成 n 个数对&#xff0c;满足&#xff1a; 每个元素 只属于一个 数对。 同一数对中的元素 相等 。 如果可以将 nums 划分成 n 个数对&#xff0c;请你返回 true &#xf…