【Linux】linux基础IO(c语言程序接口,常用文件调用详解)

张开发
2026/4/16 8:07:16 15 分钟阅读

分享文章

【Linux】linux基础IO(c语言程序接口,常用文件调用详解)
本文是小编巩固自身而作如有错误欢迎指出目录一、IO共识原理二、C语言文件接口fopen/fclosefwritefprintf输出重定向 和追加重定向 1. 输入重定向 2. 追加重定向 三、文件系统调用文件系统调用概念比特位方式传递标志位Bit Flagsopenclose注意事项writeread四、访问文件的本质文件是内核的数据结构文件描述符fd核心总结一、IO共识原理在正式学习IO之前我们先回忆一下之前学习的关于文件的知识文件 内容 属性文件分为打开的文件和没打开的文件对于打开的文件谁来打开其实是由进程打开本质是研究进程和文件的关系对于没打开的文件是放在哪里其实是放在磁盘上。我们最关注的是什么问题其实也就是是文件的存储问题即没有被打开的文件非常多那么文件如何被分门别类的放置好文件被分门别类的放置好后进而我们就可以快速的对文件进行增删查改也就是快速的找到文件二、C语言文件接口fopen/fclose函数原型#include stdio.h FILE *fopen(const char *pathname, const char *mode);pathname文件路径可以是相对路径或绝对路径。mode打开模式常用选项包括r只读文件必须存在w只写如果文件存在则清空不存在则创建a追加写如果文件不存在则创建r读写文件必须存在w读写文件存在则清空不存在则创建a读写写入操作追加到文件末尾#include stdio.h int fclose(FILE *stream);stream指向fopen返回的FILE*返回值0关闭成功EOF关闭失败这些基础用法我们在之前就已经学习过了现在重提的原因主要在于我们今天要重点了解文件换缓冲机制fopen返回的FILE*会有缓冲区默认全缓冲或行缓冲所以写入磁盘不一定是即时的。当使用fwrite或printf写入文件时数据先进入用户级缓冲区由FILE*管理并不会立即写入磁盘。fclose会确保缓冲区的数据被写入磁盘从而保证文件内容完整我们先在看一看下面的示例代码#include stdio.h #include string.h #include unistd.h int main() { const char *filename buffer_test.txt; const char *msg Hello, Linux I/O buffer!\n; // 打开文件用于写入 FILE *fp fopen(filename, w); if (!fp) { perror(fopen); return 1; } // 写入缓冲区但不调用 fclose fwrite(msg, strlen(msg), 1, fp); printf(Data written to buffer, but not yet flushed to disk.\n); printf(Check the file content with: cat %s\n, filename); // 这里注释掉 fclose 查看缓冲区效果 // fclose(fp); // 如果你取消上面 fclose 注释缓冲区会被刷新到磁盘 printf(Now closing file to flush buffer...\n); fclose(fp); printf(File closed. Buffer flushed. Check the file content again.\n); return 0; }打开文件使用fopen(buffer_test.txt, w)打开一个文件用于写入得到一个FILE*指针内部维护一个用户级缓冲区写入数据到缓冲区使用fwrite(msg, strlen(msg), 1, fp)将字符串写入缓冲区注意这时候数据还未写入磁盘仍在内存中输出提示提示用户数据已写入缓冲区但尚未刷新到磁盘可以用cat buffer_test.txt查看文件内容此时可能为空关闭文件可选调用fclose(fp)fclose会刷新缓冲区把缓冲区内的数据写入磁盘同时释放文件描述符关闭文件观察效果不调用 fclose文件内容可能为空数据仍在缓冲区调用 fclose数据写入磁盘文件显示完整内容fwrite#include stdio.h size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);ptr指向要写入的数据起始地址size每个元素的字节数nmemb要写入元素的个数stream目标文件的FILE*返回值成功写入的元素个数不是字节数fwrite写入的是用户缓冲区不是直接写磁盘fclose会刷新缓冲区并关闭文件可以用fflush(fp)代替fclose实现中途刷新缓冲区fprintf#include stdio.h int fprintf(FILE *stream, const char *format, ...);stream目标文件的FILE*format格式化字符串...对应格式的变量返回值成功写入的字符数如果出错返回负值#include stdio.h int main() { FILE *fp fopen(fprintf_test.txt, w); if (!fp) { perror(fopen 出错); return 1; } int a 42; const char *name Linux I/O; // 写入格式化内容 fprintf(fp, 这是一个测试变量 a %d, name %s\n, a, name); // 刷新缓冲区并关闭文件 fclose(fp); printf(已写入 fprintf_test.txt缓冲区已刷新。\n); return 0; }输出重定向 和追加重定向1. 输入重定向 作用将程序的标准输出stdout写入文件如果文件已存在会覆盖原文件内容2. 追加重定向作用将程序的标准输出stdout写入文件如果文件已存在内容追加到末尾三、文件系统调用文件系统调用概念文件系统调用是操作系统提供的接口允许程序访问磁盘上的文件和设备与C 标准库函数fopen/fwrite/fclose不同系统调用是直接与内核交互的比特位方式传递标志位Bit Flags在 Linux 系统调用如open中通常会有多个选项为了节省参数同时可以组合多个选项Linux 使用比特位bit表示每个选项每个选项对应整数中的一位或多位通过按位或|来组合#define O_RDONLY 0x0000 // 0000 0000 #define O_WRONLY 0x0001 // 0000 0001 #define O_RDWR 0x0002 // 0000 0010 #define O_CREAT 0x0040 // 0100 0000 #define O_APPEND 0x0400 // 0100 0000 0000int flags O_WRONLY | O_CREAT | O_APPEND;内存中的二进制表示0000 0000 0000 0001 (O_WRONLY) 0000 0000 0100 0000 (O_CREAT) 0100 0000 0000 0000 (O_APPEND) ------------------- 0100 0000 0100 0001 (组合后的 flags)节省参数一个整数可以表示多个选项易于扩展新选项只需分配新的一位组合灵活用|组合用检查open#include fcntl.h int open(const char *pathname, int flags, mode_t mode);pathname文件路径flags打开方式例如O_RDONLY只读O_WRONLY只写O_RDWR读写O_CREAT文件不存在则创建O_APPEND追加写O_TRUNC打开时清空文件mode权限位仅在创建文件时使用如 0666返回值文件描述符 fd0 表示成功-1 表示失败close#include unistd.h int close(int fd);fd文件描述符由open或其他系统调用返回返回值0→ 成功-1→ 出错并设置errno注意事项不要重复关闭同一个 fd重复调用close(fd)会导致未定义行为fd 会被操作系统重用下一个open可能会分配相同的 fd和库函数 fclose 的区别close(fd)只关闭 fdfclose(FILE* fp)先刷新缓冲区再调用closewrite#include unistd.h ssize_t write(int fd, const void *buf, size_t count);fd文件描述符由open或其他系统调用返回buf指向要写入的数据内存地址count写入字节数返回值实际写入的字节数如果出错返回 -1 并设置 errno特性writefwrite缓冲区内核缓冲区用户缓冲区 内核缓冲区调用层级系统调用内核C 标准库封装调用 write输出类型文件描述符 fdFILE*可以是 stdout、stderr 或文件刷新控制立即写入内核缓冲区需要fflush或fclose才写入内核read#include unistd.h ssize_t read(int fd, void *buf, size_t count);fd文件描述符由open或其他系统调用返回buf指向内存缓冲区用于存储读取的数据count要读取的最大字节数返回值成功 → 实际读取的字节数到文件末尾 → 返回 0出错 → 返回 -1 并设置 errno四、访问文件的本质在 Linux 中“访问文件”不仅仅是打开文件或读写文件而是操作内核中的文件系统和文件描述符文件是内核的数据结构文件在 Linux 内核中不仅是磁盘上的字节流也对应内核维护的文件结构struct file内核维护每个打开文件的状态包含文件指针读写偏移位置访问权限只读/只写/读写文件状态打开、追加、锁定等关联的 inode文件的元信息如大小、权限、设备类型文件在磁盘上的字节 内核维护的元信息 文件的本质文件描述符fd用户程序通过文件描述符 fd操作文件fd 是一个索引或句柄指向内核维护的struct fileLinux 默认0→ stdin1→ stdout2→ stderr每次open返回的 fd其实就是指向内核文件表的索引文件操作 通过 fd 间接操作内核文件结构核心总结文件不仅是磁盘上的数据更是内核维护的数据结构 元信息用户程序访问文件 通过 fd 间接操作内核文件结构所有 I/Oread/write/fread/fwrite/printf本质都是数据在用户缓冲区 ↔ 内核缓冲区 ↔ 磁盘之间流动文件描述符、缓冲区、系统调用三者构成文件访问的完整链路本次分享就到这里结束了后续会继续更新感谢阅读

更多文章