Linux文件与fd
一个程序#include stdio.h #include string.h int main() { FILE *fd fopen(hello.txt,w); if(fd NULL) { return 1; } const char *msg hello world\n; fwrite(msg, 1, strlen(msg)1, fd); fclose(fd); return 0; }运行程序之后查看一下文件的内容在上面的程序当中我们以写的方式打开了一个文件如果文件没有建立会自动帮你建立而且以写的方式打开的话你多次运行程序的话会将写的内容覆盖如果想不被覆盖的话可以采用追加的方式打开文件这都是C语言的内容我们简单的复习一下接下来才是重点为什么我们在读一个文件的时候需要先打开文件等到程序结束之后我们又要关闭文件原因就是我们的文件是在磁盘上面的当我们要写/读文件的时候打开文件实际上就是将文件加载到内存关闭就是将文件又写回磁盘上这也是我们在window电脑上面写完文件需要点击保存的原因下面我们演示一下不关闭文件就无法写入成功的情况#includestdio.h #includestring.h #includeunistd.h int main() { FILE *fdfopen(hello.txt,w); if(fdNULL) { return 1; } const char *msghello world; fwrite(msg,1,strlen(msg)1,fd); //fclose(fd); _exit(0); //return 0; //不能写这个写这个一样回刷新缓冲区看不见不关闭文件就写写失败的现象 }运行结果这个时候我们发现再查看文件的内容的话就显示为空了在文件系统当中在内存当中存在一个文件缓冲区的地方当我们一直写文件的时候内容首先回被写到缓冲区当中当满足刷新条件的时候就会将缓冲区里面的内容写到磁盘上面去这样能够避免频繁的I/O导致效率的降低将内容打印到显示器在linux中有一切皆文件的说法同样的我们的标准输入(stdin)标准输出(stdout),标准错误stderror也是一个文件对象的指针其中标准输入就是我们的键盘stdout就是显示器stderr暂时不介绍下面展示集中将文件打印到显示器的操作#include stdio.h #include string.h int main() { printf(hello world\n); fprintf(stdout, hello world\n); const char *message hello world\n; fwrite(message, 1, strlen(message), stdout); return 0; }运行结果文件操作的系统接口除了C语言标准的文件接口我们还有系统级别的文件调用接口参数介绍pathname:想要创建的文件名字这里是加上路径一起的flags:表示想要用什么样的方式去创建文件通常有下面的几种方式O_CREAT: 不存在就创建O_TRUNC 清空文件的内容O_APPEND 采用追加的方式mode:表示创建文件的使用权限关于文件的使用权在这里介绍一下上面的红色的方框里面就是文件的权限第一个字符-表示是文件 d表示是目录第二到四表示所属者的权限rwx分别表示读写执行第五到七表示所属组成员的权限rwx分别表示读写执行第八到十表示其他用户的权限rwx分别表示读写执行现在我们来写一个程序#include stdio.h #include sys/types.h #include sys/stat.h #include fcntl.h #include string.h #include unistd.h int main() { int fd open(log.txt,O_CREAT|O_TRUNC|O_WRONLY,0666); const char *buffer hello world\n; write(fd, buffer, strlen(buffer)); close(fd); return 0; }查看一下文件的内容我们解释一下上面打开文件的时候里面的参数O_CREAT|O_TRUNC|O_WRONLY这里表示没有就创建先清空文件的内容用写的方式为什么用“|”链接理解为二进制的方式每一个二进制比特位代表一种方式或运算不就是把他们都结合起来吗后面的0666是设置文件的权限都是以二进制的方式111 111 111就是拥有者所属组其他人的读写执行都设置成为1同样666的二进制是110 110 110,分析方法和上面的一样但是发现文件的权限不是这样的呀这是因为出与安全的考虑最后总是比设置的权限要低一些如果想要设置的话可以像下面的这样#include stdio.h #include sys/types.h #include sys/stat.h #include fcntl.h #include string.h #include unistd.h int main() { //umask(0); //设置umask的值为0 int fd open(log.txt, O_APPEND|O_TRUNC|O_WRONLY, 0666); const char *buffer hello world\n; write(fd, buffer, strlen(buffer)); chmod(log.txt, 0666); //改变一下权限 close(fd); return 0; }文件fd下面看一个程序#include stdio.h #include sys/types.h #include sys/stat.h #include fcntl.h #include string.h #include unistd.h int main() { //umask(0); //设置umask的值为0 int fd open(log.txt O_APPEND|O_TRUNC|O_WRONLY, 0666); printf(the fd of log.txt is %d\n, fd); close(fd); return 0; }运行结果我们发现fd居然是一个数字其实这个数字是一个下标这个下标是一个文件指针数组的下标请看下图在每一个进程的PCB里面都有有一个文件指针变量指向一个文件数组fd是这个文件数组的下标这样就能访问到对应的文件下面再看一个文件#include stdio.h #include sys/types.h #include sys/stat.h #include fcntl.h #include string.h #include unistd.h int main() { //umask(0); //设置umask的值为0 int fd1 open(log1.txt, O_CREAT|O_TRUNC|O_WRONLY, 0666); int fd2 open(log2.txt, O_CREAT|O_TRUNC|O_WRONLY, 0666); int fd3 open(log3.txt, O_CREAT|O_TRUNC|O_WRONLY, 0666); int fd4 open(log4.txt, O_CREAT|O_TRUNC|O_WRONLY, 0666); int fd5 open(log5.txt, O_CREAT|O_TRUNC|O_WRONLY, 0666); printf(the fd of log1.txt is %d\n, fd1); printf(the fd of log2.txt is %d\n, fd2); printf(the fd of log3.txt is %d\n, fd3); printf(the fd of log4.txt is %d\n, fd4); printf(the fd of log5.txt is %d\n, fd5); close(fd1); close(fd2); close(fd3); close(fd4); close(fd5); return 0; }运行结果文件fd都是连续晚上可以增长的看了上面的文件fds数组可以理解但是为什么是从3开始那012有是什么嘞其实012分别对应的就是stdin,stdout,stderr三个但是这是默认情况下系统回给文件分配最小并且没有使用的fd下面我们关闭一下stderr#include stdio.h #include sys/types.h #include sys/stat.h #include fcntl.h #include string.h #include unistd.h int main() { close(2); //关闭一下stderr int fd1 open(log1.txt, O_CREAT|O_TRUNC|O_WRONLY, 0666); int fd2 open(log2.txt, O_CREAT|O_TRUNC|O_WRONLY, 0666); int fd3 open(log3.txt, O_CREAT|O_TRUNC|O_WRONLY, 0666); int fd4 open(log4.txt, O_CREAT|O_TRUNC|O_WRONLY, 0666); int fd5 open(log5.txt, O_CREAT|O_TRUNC|O_WRONLY, 0666); printf(the fd of log1.txt is %d\n, fd1); printf(the fd of log2.txt is %d\n, fd2); printf(the fd of log3.txt is %d\n, fd3); printf(the fd of log4.txt is %d\n, fd4); printf(the fd of log5.txt is %d\n, fd5); close(fd1); close(fd2); close(fd3); close(fd4); close(fd5); return 0; }运行结果文件fd便开始从2开始了但是如果我们关闭1的话就会出现不一样的状况#include stdio.h #include sys/types.h #include sys/stat.h #include fcntl.h #include string.h #include unistd.h int main() { close(1); //关闭文件stdout对应的文件 int fd1 open(log1.txt, O_CREAT|O_TRUNC|O_WRONLY, 0666); int fd2 open(log2.txt, O_CREAT|O_TRUNC|O_WRONLY, 0666); int fd3 open(log3.txt, O_CREAT|O_TRUNC|O_WRONLY, 0666); int fd4 open(log4.txt, O_CREAT|O_TRUNC|O_WRONLY, 0666); int fd5 open(log5.txt, O_CREAT|O_TRUNC|O_WRONLY, 0666); printf(the fd of log1.txt is %d\n, fd1); printf(the fd of log2.txt is %d\n, fd2); printf(the fd of log3.txt is %d\n, fd3); printf(the fd of log4.txt is %d\n, fd4); printf(the fd of log5.txt is %d\n, fd5); close(fd1); close(fd2); close(fd3); close(fd4); close(fd5); return 0; }但是运行的时候却是什么结果都没有出现但是内容却被打印到log1.txt文件当中去了其实我们语言层的每一个函数再系统都有一个封装printf底层可能就是write函数在写的时候文件默认是stdout对对应的1当我们改变了fd就写到别的文件当中去了这也叫做重定向重定向我们结合上卖弄的例子再来理解一下重定向原本fd1默认是指向stdout的但是我们关闭fd1的文件在以新建的方式打开文件fd1就会分配给新的文件printf底层默认封装的一个函数参数中就有fd1,这个时候当我们调用printf的时候想要打印的内容就打印到了新建的文件当中去int dup2(int oldfd, int newfd);这个函数的作用就是让newfd指向oldfd所指向的文件如果newfd的文件是打开的就先关闭但是oldfd不会关闭也就是说oldfd和newfd指向同一个文件#include stdio.h #include sys/types.h #include sys/stat.h #include fcntl.h #include string.h #include unistd.h int main() { int fd open(log.txt,O_CREAT|O_TRUNC|O_WRONLY,0666); dup2(fd, 1); printf(hello world\n); fflush(stdout); //需要刷新一下缓冲区当指向文件的时候需要等缓冲区满了之后才刷新 close(1); //不管有没有\n,但是指向的是stdout的时候只要有\n就会刷新 close(fd); return 0; }运行查看log.txt文件用户级缓冲区在上面我们提到关于文件系统调用当我们在写文件的时候会有一个系统级别的缓冲区同样的我们在使用C语言的文件操作的时候也存在一个用户级别的缓冲区当我们调用C语言的文件操作的时候比如在写文件的时候先是需要将内容写到用户级别的缓冲区当中然后等到刷新刷新到系统级别的缓冲区再刷新到磁盘上面去#include iostream #include cstdio #include unistd.h using namespace std; int main() { FILE *pf fopen(log.txt,w); fprintf(pf,hello world); //写入用户级别的缓冲区 int fd fileno(pf); fsync(fd); //刷新一下系统级别的缓冲区 _exit(0); //不能用return 0或exit,会刷新用户还有系统级别 //的缓冲区 }运行我们查看log.txt文件里面确是发现什么也没有这是因为当我们调用C语言的文件函数之后刷新的是系统的缓冲区但是内容还在用户级别的缓冲区查看一下文件内容在上面的程序当中我们先刷新了用户缓冲区再刷新文件缓冲区这个时候内容才能够写到文件当中去下面我们再看一个程序#includeiostream 2 #includecstdio 3 #includeunistd.h 4 #includecstring 5 using namespace std; 6 7 8 int main() 9 { 10 printf(hello printf\n); 11 fprintf(stdout,hello fprintf\n); 12 const char *messagehello fwrite\n; 13 fwrite(message,1,strlen(message),stdout); 14 15 const char *whello write\n; 16 write(1,w,strlen(w)); 17 fork(); 18 19 return 0; 20 }直接运行当我们直接运行的时候由于是输入到显示器上的遇到换行就刷新但是当我们重新定向到文件当中去的时候就会出现不一样的效果我们发现调用C语言的打印了两次系统调用的打印了一次这是因为在fork之前调用C语言的时候内容都在用户缓冲区当中当fork之后出现父子进程父子进程分别都有用户缓冲区内容相同结束的时候各自刷新系统调用的是系统自己有的和父子进程没有关系于是调用系统的只是调用了一份

相关新闻

UI学习: 多界面传值的正向传值(属性传值)和反向传值(代理传值)

UI学习: 多界面传值的正向传值(属性传值)和反向传值(代理传值)

文章目录一、属性传值(正向传值:A → B)原理实现步骤二、代理传值(反向传值:B → A)为什么属性传值做不到反向传?代理模式三要素数据流向实现步骤三、两种传值方式对比一、属性传值(…

2026/10/19 19:48:27 阅读更多 →
python学习8 之 【集合、datetime模块、字典】

python学习8 之 【集合、datetime模块、字典】

目录 1.集合 1.1.集合的特点 1.2.集合的创建 1.3.基本操作 1.4.集合运算 1.5.集合关系判断 1.6.frozenset 2.datetime 模块 2.1.主要类 3.字典 3.2.基础操作 3.3.视图和遍历 视图对象 3.4.字典操作 3.5.创建和转换 3.6.字典比较 3.7.字典排序输出 3.8.常用模…

2026/10/10 8:58:45 阅读更多 →
上海jsp网站建设:从入门到精通,揭秘高端企业官网背后的技术逻辑与用户体验优化策略

上海jsp网站建设:从入门到精通,揭秘高端企业官网背后的技术逻辑与用户体验优化策略

在如今的互联网时代,企业官方网站早已不再是简单的“网上名片”,而是品牌实力的延伸、业务转化的核心引擎以及客户信任的基石。特别是在上海这样一座国际化大都市,竞争尤为激烈,企业对于网站的要求也呈现出前所未有的高标准。提到网站开发技术,很多人首先想到的是WordPres…

2026/9/25 22:32:45 阅读更多 →

最新新闻

低空航拍路面裂缝检测数据集:VOC+YOLO双格式标注与训练实战

低空航拍路面裂缝检测数据集:VOC+YOLO双格式标注与训练实战

低空航拍路面裂缝类型检测数据集,这个项目我前后折腾了一个多月,最终整理出3391张带完整标注的有效样本,并按VOCYOLO双格式交付。起因很简单:市场上公开的路面裂缝数据集大多来自地面手持相机或车载视角,真正贴合无人机…

2026/10/19 19:47:09 阅读更多 →
为vLLM添加自定义模型推理支持:从权重转换到启动验证

为vLLM添加自定义模型推理支持:从权重转换到启动验证

模型训练收工的那一刻,通常是最开心的;接下去要把模型送上线,才是最磨人的。手里一个小众模型,训练时用的自定义框架,checkpoint 命名随心所欲,架构和主流模型有那么点像又不完全一样。你想用 vLLM 上线&am…

2026/10/19 19:47:09 阅读更多 →
开源代码审查工具 open-code-review:自动化预审与人工把关的工程实践

开源代码审查工具 open-code-review:自动化预审与人工把关的工程实践

代码审查这件事,不少团队都卡在同一个地方:流程定下来了,工具也上了,但审查质量始终靠人肉上下文硬扛。要么是 review 的人对业务不熟,提的comments全是 style 层面;要么是 reviewer 自己忙,拖了…

2026/10/19 19:47:09 阅读更多 →
开源代码评审工具实战:从规则引擎到插件化架构的设计与部署

开源代码评审工具实战:从规则引擎到插件化架构的设计与部署

1. 为什么我会自己动手写一个代码评审工具做了这么多年开发,代码评审这件事,我一直觉得是“人人都知道重要,但很难坚持做好”的环节。团队里 code review 做得松的,基本就是合并前点个通过;做得严的,又容易…

2026/10/19 19:47:09 阅读更多 →
LangChain智能体(Agent)实战指南:从ReAct到LangGraph

LangChain智能体(Agent)实战指南:从ReAct到LangGraph

聊LangChain,绕不开的就是Agent。用过ChatGPT的人都知道,模型本身再强也只是个“建议者”,你问它今天天气如何,它只能抱歉地说自己不知道实时数据。但Agent不一样,它把模型从“会说话的百科全书”变成了“会动手办事的…

2026/10/19 19:47:09 阅读更多 →
低剂量TEM图像去噪:非局部机制如何保住晶格细节

低剂量TEM图像去噪:非局部机制如何保住晶格细节

简介:面向深度学习去噪研究的TEM-NLnet项目Demo,定位为论文复现辅助资源,适合需要理解或应用深度去噪网络的研究者与开发者。压缩包共11个文件,以10个Python脚本为主,另含1个Markdown说明文档,整体仅14KB&a…

2026/10/19 19:46:07 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →