自学嵌入式第23天(Linux系统编程篇——文件编程)
Linux系统编程由网络编程文件编程多任务编程组成。在这一篇我们主要学习的是函数的使用函数又有内核函数和库函数两种库函数是别人把内核函数封装好后使用的函数一、Linux系统基础概念1.Linux系统分层架构我们平时写的.c.txt编译出的可执行文件文件都是磁盘上按文件系统规则存储的二进制数据不能直接碰硬件我们写的函数还会调用库函数也就是别人把内核提供的函数进行封装得到的方便我们使用。系统调用是内核专门给用户空间开的官方接口以函数的方式提供从用户到内核的唯一通道。这里就是用户只能通过系统调用访问内核函数和读写硬件寄存器驱动是一个软件驱使硬件动起来的软件程序。内核空间是需要用到操作系统和硬件才会进入。我说实话这里主播也十分懵逼所以如果实在看不懂就先放下我感觉后面学着学着就明白了等这一篇学完我会在总结篇再详细说的希望那个时候我能弄明白这些。二、Linux文件编程在Linux系统中有个叫一切皆文件的说法意思就是把能当做文件的全部当做文件这样的好处是简化了对文件的处理和识别也可以使用统一的操作逻辑。这里操作逻辑是指对所有的文件我们都有先打开文件对文件进行读和写然后再关闭文件如果都看做文件那么我们就只需要进行这几步操作。1.Linux七种文件类型bblock块设备文件直接和硬件关联起来如硬盘或者外接设备如摄像头以块为单位操作一个块为512个字节。cchar字符设备文件以字节为单位其实就是内容输入端相关设备比如键盘ddirectory目录文件-regular常规文件.c.txt图片等等lsymblink连接文件相当于Windows下创建的快捷方式将桌面的一个快捷方式和内存中的软件关联起来。sscoket套接字文件ppipe管道文件让不同的文件可以通信三、文件操作函数接下来进入这一篇的正题下面的内容无论如何都要记住。其实这是两天写了一篇经过几天主播的学习我总结出来其实就是用库函数方式和系统调用方式完成文件打开然后对其进行读写然后再关闭它但是这两种方式都是调用函数只是库函数是经过别人封装的用起来更方便一点系统调用的函数和内核里面的一些东西更近一点。库函数这张图就是用户态标准 IO 库FILE*→ 经过系统调用切换内核态 → 内核三层文件管理结构 → 最终访问磁盘文件的流程stdin标准输入stdout标准输出stderr标准错误这三个文件是默认打开的标准流后面我们通过库函数或者系统调用打开的文件都会有一个文件描述符表fd这个描述符会将当前最小的描述符分给现在打开的这个文件。文件表项中会记录打开模式、文件读写偏移量、引用计数、指向 vnode 的指针vnodeinode节点 存储文件元数据文件大小、权限、磁盘数据块位置等最终指向磁盘上真实文件。这块很重要后面会用到1.fopen头文件#include stdio.h #include fcntl.h形式FILE *fopen(const char* pathname , const char *mode);功能流打开函数打开pathname指定的文件并关联一个流给这个文件。参数pathname是要打开的文件名mode是打开的模式据以有以下几种模式全称读写权限文件不存在文件已存在文件指针初始位置核心特点rread只读打开失败返回 NULL正常打开文件开头不能写入不会清空原有内容wwrite只写创建新空白文件直接清空原有全部内容文件开头慎用打开瞬间就清空旧文件aappend只写追加创建新空白文件保留原有内容文件末尾永远只能在末尾写无法修改前面数据rread可读可写打开失败返回 NULL正常打开文件开头可读可写不会清空文件wwrite可读可写创建新空白文件直接清空原有全部内容文件开头先清空文件之后既能读又能写aappend可读可写创建新空白文件保留原有内容文件末尾写数据永远追加到末尾读可以任意位置返回值成功时返回FILE*指针也就是指向打开文件的指针失败时返回NULL并设置errno可以通过perror“”来打印错误原因到时候会在终端显示“”内信息错误原因2.fclose头文件#includestdio.h形式int fclose (FILE *stream)功能关闭流并释放相关内存空间参数stream是要关闭的文件返回值成功时返回0失败时返回EOFend of file是一个宏定义其实就是-1errno被设置。注意同一个文件不能多次fclose下面为三组读写函数1.fgetc形式int fgetc(FILE *stream)功能单个字符输入函数参数stream是要读取的文件这里实参都是文件指针返回值成功返回读到的字符返回值是int型其实就是字符的ascii码失败返回EOF读到文件末尾也返回EOF。2.fputc形式int fputc (int c,FILE *stream)功能输出单个字符参数c为要输出的字符stream是输出到哪个文件返回值成功时返回输出字符的ascii码失败时返回EOF例子通过这两个函数实现复制文件将第一个文件复制为第二个所以第二个文件只读第二个文件只写fgetc读取一个字符判断是不是EOF不是的话就写入第二个文件。直到读到EOF结束最后关闭两个文件。3.fgets形式char *fgets(char *s,int SIZE,FILE *scream)功能从stream中最多读取SIZE-1个字符放到s中参数s是个字符型数组的指针SIZE是一次读取的字符数返回值成功返回s失败返回NULL读取结束的情况1读到EOF也就是文件末尾2读到\n结束\n会被保存在s中3读到SIZE-1个字符读取结束后会在最后加\0所以只能读SIZE-1个字符4.fputs形式int fputs (const char *s,FILE *stream)功能将s中的内如输出到stream文件输出是不输出\0参数s为要输出的字符串返回值成功时返回非负数失败时返回EOF例子这个是利用fgets和fputs实现的文件复制打开文件和关闭文件部分一样只是读写部分不一样读取buf大小的字节放到buf中如果没读到结尾就将buf中的内容放到目标文件。这里给1024是为了减少内存碎片其实不要这么大也行前面说过fgets遇到\n也会结束这时候buf没读满返回值是buf的地址。下面的这个读写是按二进制读写按对象学习。5.fread形式size_t fread ( void *ptr, size_t size, size_t nmemb, FILE *stream) ;功能:读取二进制数据参数ptr保存数据一块空间size单个元素的大小nmemb元素的个数这里要说的就是字节数元素的大小*元素个数返回值成功返回读取到或写入的元素个数失败返回06.fwrite形式size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) ;功能:写入二进制数据参数ptr保存数据一块空间size单个元素的大小nmemb元素的个数返回值成功返回读取到或写入的元素个数失败返回0例子这里的这个例子不止是复制一个文件了这里还计算了源文件fp_s的字节长度然后生成了一个空洞文件就是一个内容全是\0的文件用来抢占磁盘就是看看磁盘中的位置够不够放下一个这么大的文件如果不够就直接提示内存不够就不复制文件了需要好好理解一下。下面这两个函数都属于定位函数更改的是读写指针的位置。7.fseek形式int fseek (FILE *stream, long offset, int whence);功能:移动文件读写指针的位置用来自由定位文件偏移量常配合 ftell 获取文件大小参数poffset偏移字节数正数向后偏移、负数向前偏移whence偏移基准起点共 3 种取值。SEEK_SET文件开头SEEK_CUR指针当前位置SEEK_END文件末尾返回值定位成功返回 0定位失败返回非 0 数值。注意当偏移基准点为SEEK_SET时偏移量不能为负数当文件为空时桑偏移量基准点时一样的都在开头当偏移量超过文件字节数时还是会偏移这么多但是如果不往文件里面写内容就还是原字节数如果偏移完后写入一个字节那么就会使偏移量1的字节数。8.ftell形式long ftell (FILE *stream);功能:获取当前文件指针距离文件开头的字节偏移量最常用场景是计算文件总长度参数stream需要查询的文件指针返回值正常返回当前偏移字节数出错返回 - 1。void rewind(FILE *stream);也是定位函数将读写指针移动到文件开头。在这个代码中我们进行了将读写指针移动到文件末尾读完长度后与移动到文件开头以及创建一个空洞文件之后又将读写指针移动到文件开头这是为什么呢因为这里有个非常重要的知识点——缓存区。8.缓存标准I0:把文件的操作 抽象了对流的操作所以标准Io都是围绕FILE*指针进行的。并设计缓存---缓冲区为啥缓冲区能提高效率?缓冲区之所以能够提升读写效率本质是因为直接读写磁盘需要调用read、write这类系统调用程序要在用户态与内核态之间来回切换再加上磁盘寻道本身耗时较长倘若每次仅读写一字节就发起一次系统调用频繁的状态切换和磁盘访问会造成极大性能损耗标准IO会在用户空间开辟高速内存缓冲区写入数据时内容会先暂存于缓冲区中暂缓落盘直至缓冲区存满、遇见换行符、程序结束或是手动执行fflush刷新时才将积攒完毕的整块数据通过一次系统调用统一写入磁盘读取数据也会预先批量加载一大段内容到缓冲区后续直接从内存调取这样就把海量细碎的小块IO请求整合为为数不多的大块IO操作大幅削减了用户态内核态切换次数与磁盘访问频次同时内存读写速度远高于硬盘连续批量读写也规避了机械硬盘零散写入的低效问题最终显著提升整体读写效率。那么缓存什么时候会刷新呢主要分为以下三种缓存他们在不同的情况下进行刷新1行缓存大小1k主要用于人机交互stdout行缓存多是关于终端的一些操作刷新条件a.遇到\n刷新b.缓存区满刷新c.程序结束刷新d.fflush刷新fflush(stdout);强制刷新2全缓存4k主要用于文件的读写对普通文件进行标准IO操作建立的缓存一般为全缓存刷新条件a.缓存区满刷新b.程序结束刷新c.fflush来刷新fflush(fp);3不缓存主要用于出错处理信息的输出stderr不对数据缓存直接刷新fprintf(strerr, fopen error %s,filename) ;strerr是界面交互fopen error出错处理由此可知我们在上面的代码中计算文件所占字节数计算完后读写指针处于文件末尾那等我们读这个文件内容时就会读不到内容创建完空洞文件后读写指针也是在文件最后如果不将其放到文件开头那么在写的时候就会接着在\0后面写所占内存也就直接翻倍了。所以在库函数操作文件时一定要时刻注意读写指针的位置。系统调用文件描述符表示打开文件的整数他的分配原则是将最小未使用整数分给当前打开的文件。这里就又要提到这张图了库函数是上层用户空间先缓存攒够数据后才跨过中线触发系统调用系统调用是调用 fd 系列接口直接从系统调用分界线开始向下执行。所以库函数其实就是有个缓冲区在数据达到一定程度在调用系统调用而文件IO系统调用就是直接使用系统调用没有缓存。1.open需要用到的头文件#include sys/types.h#include sys/stat.h#include fcntl.h形式int open(const char *pathname, int flags, mode_t mode);功能:打开文件参数pathname是文件名。flags是打开模式标志位O_RDONLY只读打开O_WRONLY只写打开O_RDWR读写打为必选一个。还可根据需求自己增加附加标志以达到需求多个标志位之间以|(或)连接。O_CREAT文件不存在则新建使用此参数必须带上第三个 mode 参数O_TRUNC文件存在清空原有内容O_APPEND追加写入永远从文件末尾写。mode是新建文件的权限。一遍写为0666具体原因下一篇介绍。返回值成功返回非负整数失败返回-1同时设置 errno 错误码2.close形式int close(int fd);功能:关闭文件参数fd是文件名。返回值成功返回 0失败返回 -13.read形式size_t fread ( void *ptr, size_t size, size_t nmemb, FILE *stream) ;功能:读取数据参数fdopen 返回的有效文件描述符buf缓冲区内存地址读取的数据会存入这块内存count期望读取的字节最大长度返回值0成功读到的字节数 0读到文件末尾 EOF无数据可读 -1读取出错4.write形式 ssize_t write(int fd, const void *buf, size_t count);功能:读取二进制数据参数fd可写的文件描述符buf要写入数据的缓冲区首地址count想要写入的字节数量返回值0实际成功写入的字节数正常等于 count0未写入任何数据-1写入失败5.lseek形式off_t lseek(int fd, off_t offset, int whence);功能:定位读写指针参数int fd 打开文件得到的文件描述符open的返回值off_t offset 偏移字节数有正负正数向文件末尾方向 向后偏移负数向文件开头方向 向前偏移int whence 偏移基准起点只有 3 个固定宏SEEK_SET 文件开头起始位置SEEK_CUR 文件指针当前所在位置 SEEK_END 文件末尾。返回值成功返回调整后新的文件偏移总量距离文件开头的字节数失败返回-1例题这里还是很简单的看看怎么用就行。对比对比项目标准 IO系统调用打开 /关闭fopen、fcloseopen、close读写接口fgetc/fgets/fread、fputc/fputs/fwrite、read、write文件定位fseek、ftell、rewindlseek缓冲区自带用户空间缓冲区行缓冲 / 全缓冲 / 无缓冲无用户缓冲区每次调用直接进入内核操作标识FILE* 文件流指针int 文件描述符 fd优点1. 自带缓冲小块频繁 IO 效率更高2. 接口丰富易用支持格式化输出 printf3. 跨平台Windows/Linux 均可使用1. 无缓存延迟数据可即时落盘2. 占用资源更少底层可控性强4. 无缓冲区数据丢失隐患缺点1. 存在缓冲区延迟未刷新时数据暂存内存程序崩溃易丢数据2. fseek 受缓冲区影响指针偏移逻辑更复杂3. Linux 特殊文件管道、socket适配差1. 频繁小块读写会产生大量用户态内核态切换性能低下2. 没有格式化打印拼接字符串繁琐3. 仅类 Unix 系统可用不跨平台选择在高频IO操作但数据量不是很大的时候使用标准IO低频但数据量大以及操作设备文件时都使用系统调用。怎么说呢主播也是第一次学这个虽然好像全是函数没有很难但是我感觉有很多没听过的名词虽然好像不是很难吧但是还是感觉学的乱七八糟的目前正在努力中如果后面学明白了一定会出一个清晰版的希望能帮助到大家。

相关新闻

Kimi    LeetCode 3906. 统计网格路径中好整数的数目 C语言实现

Kimi LeetCode 3906. 统计网格路径中好整数的数目 C语言实现

以下是 LeetCode 3906 的 C 语言实现&#xff0c;采用数位 DP 思路。由于 C 没有内置的递归记忆化&#xff0c;使用静态数组手动实现记忆化搜索。c #include <stdio.h> #include <stdlib.h> #include <string.h>// 全局/静态变量用于 DFS static bool key[16…

2026/10/12 0:28:33 阅读更多 →
部署上线:Docker容器化与云端部署

部署上线:Docker容器化与云端部署

摘要&#xff1a;MCP Server Docker容器化部署教程&#xff0c;涵盖Dockerfile编写、多阶段构建、环境变量注入、健康检查和云端部署&#xff08;AWS/Aliyun&#xff09;&#xff0c;附docker-compose完整配置。 MCP部署上线 Docker容器化与云端部署 我第一次部署MCP Server到…

2026/10/10 18:04:26 阅读更多 →
串口调试工具SerialPortUtiliti安装包百度网盘

串口调试工具SerialPortUtiliti安装包百度网盘

【超级会员V1】通过百度网盘分享的文件&#xff1a;Serial P… 链接:https://pan.baidu.com/s/1H8b8myp_sx6lfnnLBDAkFA 提取码:094q 复制这段内容打开「百度网盘APP 即可获取」

2026/10/13 2:17:59 阅读更多 →

最新新闻

AI助手会话记录批量导出实战:从API到浏览器脚本的完整方案

AI助手会话记录批量导出实战:从API到浏览器脚本的完整方案

1. 把需求掰开揉碎&#xff1a;你要的批量导出到底是什么时不时就有人来问&#xff1a;能不能把AI助手左侧那一长串会话记录一次性导出&#xff1f;注意&#xff0c;这里的“会话”指的是左边列表里的每一个独立条目&#xff0c;而不是某个会话里的几十轮来回。每条会话都有自己…

2026/10/13 11:39:13 阅读更多 →
OneLive私有化直播系统搭建全攻略:从推流到播放的完整实践

OneLive私有化直播系统搭建全攻略:从推流到播放的完整实践

第一次把 OneLive 这个名字写在架构图上&#xff0c;是在帮一个朋友做线上分享活动的时候。他当时需要的不是某个直播平台的账号&#xff0c;而是一套能装在自有服务器上、由自己完全控制推拉流、录制和权限的直播项目。OneLive 这个名字就这么随手起了&#xff1a;一场直播、一…

2026/10/13 11:39:13 阅读更多 →
Open Code Review:从形式评审到协作基础设施的范式升级

Open Code Review:从形式评审到协作基础设施的范式升级

1. “open-code-review”不是个工具&#xff0c;而是一套被低估的协作范式你有没有遇到过这样的场景&#xff1a;团队里新来一位同事&#xff0c;第一天就提了三份PR&#xff0c;每份都改了二十多个文件&#xff0c;commit message写的是“fix bug”&#xff1b;或者自己花三天…

2026/10/13 11:39:13 阅读更多 →
基于人脸识别的照片视频管理器:C#稳定版64位实现

基于人脸识别的照片视频管理器:C#稳定版64位实现

简介&#xff1a;这是一款用C#编写的本地照片与视频管理工具&#xff0c;面向需要按人物整理个人影像资料的普通用户与开发者。它支持jpg、jpeg、png、bmp等图片格式以及avi、mp4、mpg、mpeg等视频格式&#xff0c;核心能力包括人脸库录入、照片视频人脸自动识别&#xff0c;以…

2026/10/13 11:39:13 阅读更多 →
AI编程智能体分级:决策权归属决定项目成败

AI编程智能体分级:决策权归属决定项目成败

1. 为什么“智能体分级”不是技术炫技&#xff0c;而是项目落地的生死线最近帮某高校实验室做一套教学辅助系统时&#xff0c;团队最初信心满满&#xff1a;用最新开源大模型Agent框架&#xff0c;两周就能跑通自动出题、批改、反馈闭环。结果卡在第三天——学生提交一道开放性…

2026/10/13 11:39:13 阅读更多 →
大模型与电机控制之间:三层分布式架构的工业落地实践

大模型与电机控制之间:三层分布式架构的工业落地实践

1. 从“一句话控制电机”的幻觉说起这两年大模型火得不行&#xff0c;不少做工业自动化的朋友私下问我&#xff1a;既然大模型连代码都能写&#xff0c;能不能让它直接控制电机&#xff1f;把产线上的PLC换掉&#xff0c;用自然语言让机械臂干这干那&#xff0c;听起来实在太有…

2026/10/13 11:38:11 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目&#xff0c;我最大的感受是&#xff0c;大部分坑不是出在技术前沿&#xff0c;而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节&#xff0c;最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了&#xff0c;很难不碰到舵机控制这道坎。做智能小车要转方向&#xff0c;做机械臂要抬关节&#xff0c;做云台要偏航俯仰&#xff0c;背后都是同一个东西在干活&#xff1a;舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”&#xff1f;——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台&#xff1f;或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜&#xff1f;又或者&#xff0c;在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介&#xff1a;基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码&#xff0c;面向计算机相关专业课程设计与期末大作业学生&#xff0c;以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程&#xff0c;…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程&#xff1a;键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化&#xff0c;十个新手有八个栽在"往输入框里填东西"这件事上&#xff1a;要么填不进去&#xff0c;要么填了一半&#xff0c;要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程&#xff1a;阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀&#xff1a;什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面&#xff0c;跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 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/12 21:05:09 阅读更多 →
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/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练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/12 18:11:17 阅读更多 →