尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
【Linux系统编程】缓冲区
1.内核缓冲区页缓存在操作系统内部文件加载到内存过程中不是直接加载到用户程序内存中的而是先加载到内核缓冲区页缓存再拷贝至用户内存中这样做可以实现权限隔离防止用户程序破坏内核数据。当操作系统需要读取数据时它通过文件描述符找到对应的struct file结构体从中获取当前读写位置的偏移量f_pos并根据f_pos计算出要访问的文件页索引。然后操作系统以inode 页索引为键值在页缓存中进行查找以此判断所需数据是否已经在内存中。如果查找到了说明数据已在内存直接复制到用户空间即可如果未查找到则需要从磁盘读取到页缓存中再复制给用户程序。struct file { struct path f_path; // 文件路径 struct inode *f_inode; // 指向文件元数据大小、权限等 loff_t f_pos; // 当前读写位置偏移量 unsigned int f_flags; // 打开标志O_RDWR, O_NONBLOCK等 atomic_t f_count; // 引用计数多少个 fd 指向它 const struct file_operations *f_op; // 函数指针read/write等 // ... };也就是说read/write本质实际是拷贝函数因为从数据流动的角度来看read 和write的核心工作就是把数据从一处搬运到另一处而且数据本身没有发生任何变化只是复制了一份。内核缓冲区存在的意义分散的IO请求数据聚合在一起通过少量的IO操作进行设备写入提高整机效率缓冲区的刷新策略常规立即刷新行刷新行缓冲一般用与显示器全缓冲写满比如OS普通文件特殊强制刷新进程退出的强制刷新2. 语言缓冲区先看一个现象从中分析不难发现由于向显示器打印是行刷新所以C的库函数打印内容都刷新到了内核缓冲区进程结束后就打印到了显示器上而如果是写入到文件的话由于是全缓冲输出内容都还在语言缓冲区里面没有被写入内核缓冲区fork之后创建的子进程将这部分继承了下来等进程结束后强制刷新导致C相关的库函数打印了两次。实际上printf/fprintf/fputs的本质都是拷贝函数当他们将内容都输出到语言缓冲区后就认为自己的任务完成了而不需要再等到OS做的一些列操作提高了应答效率。所以缓冲区的核心作用是提高IO的应答效率解决的是使用缓冲区的“人”的效率问题。3.手写stdio简易版//my_stdio.h #pragma once typedef struct { int fd; int flags; int mode; // 刷新策略 char outbuffer[1024]; int cap; int size; //char inbuffer[1024]; }My_FILE; #define NONE_CACHE 1 #define LINE_CACHE 2 #define FULL_CACHE 4 My_FILE *Myfopen(const char *pathname, const char *mode); // r w a int Myfwrite(const char *message, int size, int num, My_FILE *fp); void Myfflush(My_FILE *fp); void Myfclose(My_FILE *fp); //my_stdio.c #include my_stdio.h #include string.h #include sys/stat.h #include sys/types.h #include fcntl.h #include stdlib.h #include unistd.h static mode_t gmode 0666; // My_FILE *fp Myopen(log.txt, a); My_FILE* Myfopen(const char* pathname, const char* mode) // r w a { if (pathname NULL || mode NULL) return NULL; umask(0); int fd 0; int flags 0; if (strcmp(mode, w) 0) { flags O_CREAT | O_WRONLY | O_TRUNC; fd open(pathname, flags, gmode); (void)fd; } if (strcmp(mode, r) 0) { flags O_RDONLY; fd open(pathname, flags); (void)fd; } if (strcmp(mode, a) 0) { flags O_CREAT | O_WRONLY | O_APPEND; fd open(pathname, flags, gmode); (void)fd; } else {} if (fd 0) return NULL; //创建my_FILE对象 My_FILE* fp (My_FILE*)malloc(sizeof(My_FILE)); if (!fp) return NULL; fp-fd fd; fp-flags flags; fp-mode LINE_CACHE; fp-cap 1024; fp-size 0; //fp-outbuffer[0] \0; memset(fp-outbuffer, 0, sizeof(fp-outbuffer)); return fp; } int Myfwrite(const char* message, int size, int num, My_FILE* fp) { if (message NULL || fp NULL) return -1; // 向C文件里面写本质是向缓冲区写 int total size * num; if (total fp-size fp-cap - 1) return -1; // 写入 memcpy(fp-outbuffer fp-size, message, total); fp-size total; fp-outbuffer[fp-size] 0; if (fp-outbuffer[fp-size - 1] \n (fp-mode LINE_CACHE)) Myfflush(fp); return num; } void Myfflush(My_FILE* fp) { if (!fp) return; // 判断是否刷新, 这不就是刷新吗 if (fp-size 0) { // 系统调用 // 从用户缓冲区拷贝到内核, WB, Write Back write(fp-fd, fp-outbuffer, fp-size); fp-size 0; // WT, Write Through // 不仅仅要写入到内核缓冲区必须给我写到对应的硬件上 fsync(fp-fd); } } void Myfclose(My_FILE* fp) { if (!fp) return; Myfflush(fp); close(fp-fd); } //main.c #include my_stdio.h #include string.h #include unistd.h int main() { My_FILE *fp Myfopen(log.txt, a); if(!fp) return 1; int cnt 10; const char* msg hello world ; while(cnt--) { Myfwrite(msg, 1, strlen(msg), fp); Myfflush(fp); sleep(2); } Myfclose(fp); return 0; }
RELATED

相关推荐

Nuke Survival Toolkit:企业级合成技术栈的架构演进与工程实践

Nuke Survival Toolkit:企业级合成技术栈的架构演进与工程实践

Nuke Survival Toolkit:企业级合成技术栈的架构演进与工程实践 【免费下载链接】NukeSurvivalToolkit_publicRelease public version of the nuke survival toolkit 项目地址: https://gitcode.com/gh_mirrors/nu/NukeSurvivalToolkit_publicRelease 在影视特…

📅 2026/9/9 21:08:47
3步构建专业级GB28181国标视频监控平台:wvp-GB28181-pro快速部署指南

3步构建专业级GB28181国标视频监控平台:wvp-GB28181-pro快速部署指南

3步构建专业级GB28181国标视频监控平台:wvp-GB28181-pro快速部署指南 【免费下载链接】wvp-GB28181-pro 基于GB28181-2016、部标808、部标1078标准实现的开箱即用的网络视频平台。自带管理页面,支持NAT穿透,支持海康、大华、宇视等品牌的IPC、…

📅 2026/8/23 1:52:06
Fate/Grand Automata:FGO玩家的终极自动化解放指南

Fate/Grand Automata:FGO玩家的终极自动化解放指南

Fate/Grand Automata:FGO玩家的终极自动化解放指南 【免费下载链接】FGA Auto-battle app for F/GO Android 项目地址: https://gitcode.com/gh_mirrors/fg/FGA 你是否厌倦了在《Fate/Grand Order》中反复点击相同的副本、执行相同的操作?Fate/Gr…

📅 2026/9/15 14:05:13
MORE NEWS

更多资讯

📰

Apache Thrift 的 Common Lisp 客户端/服务端开发完全指南:从 IDL 翻译到 RPC 实战

Apache Thrift 的 Common Lisp 客户端/服务端开发完全指南:从 IDL 翻译到 RPC 实战 【免费下载链接】thrift Apache Thrift 项目地址: https://gitcode.com/gh_mirrors/thrift2/thrift 导读 本文基于 Apache Thrift 仓库中 lib/cl/README.md 官方文档&#…

📰

Genex词法分析器深度解析:状态机如何精准切分复杂规则文本

Genex词法分析器深度解析:状态机如何精准切分复杂规则文本 【免费下载链接】genex-cj 生成表达式(Generate Expression,简称:Genex或GE)是一款用于按照指定语法规则随机或固定生成数据的功能库。主要适用于依赖规则数据…

📰

PaddleHub 语言模型(Language Model)模块实战指南:词嵌入、语义匹配与预训练语义模型全解析

人工智能大模型微调模型推理服务 【免费下载链接】PaddleFormers PaddleFormers is an easy-to-use library of pre-trained large language model zoo based on PaddlePaddle. 项目地址: https://gitcode.com/gh_mirrors/pa/PaddleFormers 点击查看 免费下载 本指…

📰

openFrameworks 图像抠色实战:用像素级遍历实现蓝幕(Chroma Key)算法

图形学音视频 【免费下载链接】openFrameworks openFrameworks is a community-developed cross platform toolkit for creative coding in C. 项目地址: https://gitcode.com/gh_mirrors/op/openFrameworks 点击查看 免费下载 导读 本篇技术指南以 openFramework…

📰

tchMaterial-parser:一键批量下载电子课本PDF

tchMaterial-parser:一键批量下载电子课本PDF 【免费下载链接】tchMaterial-parser 国家中小学智慧教育平台 电子课本下载工具,帮助您从智慧教育平台中获取电子课本的 PDF 文件网址并进行下载,让您更方便地获取课本内容。 项目地址: https:…

📰

输入的“字符串”实际上是一个由 ASCII 字符组成的十六进制字符串,且 LabVIEW 在这里使用了小端字节序(Little-Endian)转换或者按字节/半字反转的逻辑

一、 关键解析逻辑纠正 输入的“字符串”实际上是一个由 ASCII 字符组成的十六进制字符串,且 LabVIEW 在这里使用了小端字节序(Little-Endian)转换或者按字节/半字反转的逻辑: **14 偏移量,长度 2**: 截取到 ASCII 字符串 "6345"。 字节反转(由于每 2 个字符…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬