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

Linux——缓冲区封装系统文件操作

在这里插入图片描述


📘北尘_:个人主页

🌎个人专栏:《Linux操作系统》《经典算法试题 》《C++》 《数据结构与算法》

☀️走在路上,不忘来时的初心

文章目录

  • 一、FILE
  • 二、封装系统接口实现文件操作
    • 1、text.c
    • 2、mystdio.c
    • 3、mystdio.h



一、FILE

因为IO相关函数与系统调用接口对应,并且库函数封装系统调用,所以本质上,访问文件都是通过fd访
问的。
所以C库当中的FILE结构体内部,必定封装了fd。
来段代码在研究一下

#include <stdio.h>
#include <string.h>
int main()
{const char *msg0="hello printf\n";const char *msg1="hello fwrite\n";const char *msg2="hello write\n";printf("%s", msg0);fwrite(msg1, strlen(msg0), 1, stdout);write(1, msg2, strlen(msg2));fork();return 0;}

运行出结果:

hello printf
hello fwrite
hello write

但如果对进程实现输出重定向呢? ./hello > file , 我们发现结果变成了:

hello write
hello printf
hello fwrite
hello printf
hello fwrite

我们发现 printf 和 fwrite (库函数)都输出了2次,而 write 只输出了一次(系统调用)。为什么呢?肯定和
fork有关!

一般C库函数写入文件时是全缓冲的,而写入显示器是行缓冲。
printf fwrite 库函数会自带缓冲区(进度条例子就可以说明),当发生重定向到普通文件时,数据的缓冲方式由行缓冲变成了全缓冲。
而我们放在缓冲区中的数据,就不会被立即刷新,甚至fork之后,但是进程退出之后,会统一刷新,写入文件当中。
但是fork的时候,父子数据会发生写时拷贝,所以当你父进程准备刷新的时候,子进程也就有了同样的一份数据,随即产生两份数据。
write 没有变化,说明没有所谓的缓冲。
综上: printf fwrite 库函数会自带缓冲区,而 write 系统调用没有带缓冲区。另外,我们这里所说的缓冲区,
都是用户级缓冲区。其实为了提升整机性能,OS也会提供相关内核级缓冲区。

缓冲区存在于FILE结构体内


二、封装系统接口实现文件操作

1、text.c

在这里插入图片描述

2、mystdio.c

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3、mystdio.h

在这里插入图片描述


相关文章:

  • 3.WEB渗透测试-前置基础知识-快速搭建渗透环境(上)
  • 手写commonJS里面的require函数
  • 基于相位的运动放大:如何检测和放大难以察觉的运动(01/2)
  • 【Java EE初阶二十一】http的简单理解(二)
  • 数据结构 计算结构体大小
  • Spring Boot 手写starter!!!
  • 第二章、FFmpeg增加RTP协议外部扩展信息解析
  • 蓝桥杯嵌入式第12届真题(完成) STM32G431
  • 内核内存回收关键隐藏变量之page引用计数
  • unity学习(38)——创建(create)角色脚本(panel)--EventSystem
  • 前端不传被删记录的id怎么删除记录,或子表如何删除记录
  • 【深度学习目标检测】十九、基于深度学习的芒果计数分割系统-含数据集、GUI和源码(python,yolov8)
  • 【C语言】详解计算机二级c语言程序题
  • uni-app 经验分享,从入门到离职(四)——页面栈以及页面跳转的 API(开发经验总结)
  • R语言入门笔记2.5
  • [译] React v16.8: 含有Hooks的版本
  • __proto__ 和 prototype的关系
  • Android组件 - 收藏集 - 掘金
  • HTTP--网络协议分层,http历史(二)
  • k8s 面向应用开发者的基础命令
  • laravel 用artisan创建自己的模板
  • leetcode388. Longest Absolute File Path
  • MQ框架的比较
  • nodejs:开发并发布一个nodejs包
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • Spring Cloud Alibaba迁移指南(一):一行代码从 Hystrix 迁移到 Sentinel
  • Unix命令
  • 高程读书笔记 第六章 面向对象程序设计
  • 免费小说阅读小程序
  • 前端面试之CSS3新特性
  • 微信公众号开发小记——5.python微信红包
  • 一、python与pycharm的安装
  • 异常机制详解
  • 智能合约Solidity教程-事件和日志(一)
  • [地铁译]使用SSD缓存应用数据——Moneta项目: 低成本优化的下一代EVCache ...
  • #我与Java虚拟机的故事#连载12:一本书带我深入Java领域
  • (32位汇编 五)mov/add/sub/and/or/xor/not
  • (Redis使用系列) Springboot 实现Redis消息的订阅与分布 四
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (搬运以学习)flask 上下文的实现
  • (附源码)基于SpringBoot和Vue的厨到家服务平台的设计与实现 毕业设计 063133
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (原)记一次CentOS7 磁盘空间大小异常的解决过程
  • .Net 6.0 处理跨域的方式
  • .NET core 自定义过滤器 Filter 实现webapi RestFul 统一接口数据返回格式
  • .NET 设计模式初探
  • .NET/C# 异常处理:写一个空的 try 块代码,而把重要代码写到 finally 中(Constrained Execution Regions)
  • .NET命令行(CLI)常用命令
  • 。。。。。
  • @Query中countQuery的介绍
  • @require_PUTNameError: name ‘require_PUT‘ is not defined 解决方法
  • [ vulhub漏洞复现篇 ] JBOSS AS 4.x以下反序列化远程代码执行漏洞CVE-2017-7504
  • [2024] 十大免费电脑数据恢复软件——轻松恢复电脑上已删除文件
  • [240527] 谷歌 CEO 承认 AI 编造虚假信息问题难解(此文使用 @gemini 命令二次创作)| ICQ 停止运作
  • [APUE]进程关系(下)