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

Linux 系统编程入门:从文件 IO 到标准库,一篇就够

一、Linux 系统编程:站在系统的肩膀上开发

1.1 什么是 Linux 系统编程?

简单说:在 Linux 系统上,调用系统提供的函数,实现想要的功能

  • 比如:写一个音乐播放器,需要从网络下载歌曲(网络编程)、保存到本地(文件编程)、多线程播放(多任务编程)。
  • 核心思想:Linux 下一切皆文件,设备、管道、Socket 都被抽象成文件,用统一的文件接口操作。

1.2 Linux 内核与用户空间

Linux 系统被严格划分为两层:

  • 内核空间(Kernel):管理硬件、内存、进程、网络等核心功能,只有内核能直接操作硬件。
  • 用户空间(User):我们写的应用程序运行在这里,不能直接操作硬件,必须通过系统调用库函数向内核发起请求。

两种实现功能的路径

  1. 直接系统调用:用 Linux 原生提供的函数(比如write),更底层、更高效。
  2. 库函数调用:用封装好的库(比如 C 标准库stdio),更易用、跨平台。

二、Linux 文件:一切皆文件

2.1 7 种文件类型

Linux 把所有资源都抽象成文件,用ls -l命令可以看到文件类型:

类型符号例子说明
普通文件-1.txtmp3jpg存储数据、文本、音视频等
目录文件dtest/管理文件集合
字符设备c/dev/input/dev/tty按字节流操作的设备(键盘、鼠标)
块设备b/dev/sda按块操作的设备(硬盘)
链接文件llibc.so -> libc.so.6软链接,类似 Windows 快捷方式
套接字ssocket网络通信、进程间通信
管道ppipe进程间通信

2.2 文件操作的基本流程

无论什么文件,操作逻辑都一样:

打开 → 读/写 → 关闭
  • 打开:获取文件的操作权限,关联一个「流」。
  • 读 / 写:操作文件数据。
  • 关闭:释放资源,保存数据。

三、标准 IO(stdio):库函数的便捷操作

标准 IO 是 C 标准库提供的文件操作函数,封装了系统调用,自带缓冲区,使用更简单、效率更高。

3.1 核心概念:流(Stream)

  • :对数据读写过程的抽象,用FILE*指针表示。
  • Linux 默认打开 3 个流:
    • stdin:标准输入(键盘),FILE*指针。
    • stdout:标准输出(屏幕)。
    • stderr:标准错误输出。

3.2 打开文件:fopen

#include <stdio.h> FILE *fopen(const char *pathname, const char *mode);
  • 参数
    • pathname:文件路径(比如"1.txt")。
    • mode:打开模式,决定读写行为:
      模式含义不存在时
      r只读报错
      w只写创建(清空原有内容)
      a追加创建(在末尾写入)
      r+读写报错
      w+读写创建(清空原有内容)
      a+读写创建(在末尾写入)
  • 返回值:成功返回FILE*流指针,失败返回NULL

示例

FILE *fp = fopen("1.txt", "r"); if (fp == NULL) { perror("fopen failed"); // 打印错误信息 return -1; }

3.3 关闭文件:fclose

int fclose(FILE *stream);
  • 功能:关闭流,释放资源,刷新缓冲区。
  • 注意:同一个文件只需关闭一次,关闭后不能再操作。

3.4 读写文件:4 组核心函数

1. 按字符读写:fgetc/fputc
int fgetc(FILE *stream); // 读一个字符 int fputc(int c, FILE *stream); // 写一个字符
  • 每次读写 1 个字符,适合文本文件。
  • 到达文件末尾返回EOF(-1)。
2. 按行读写:fgets/fputs
char *fgets(char *s, int size, FILE *stream); // 读一行 int fputs(const char *s, FILE *stream); // 写一行
  • fgets:最多读size-1个字符,自动在末尾加\0,遇到\n停止。
  • fputs:写字符串,不自动加\n
3. 按对象读写:fread/fwrite(最通用)
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); // 读 size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); // 写
  • 功能:读写nmemb个元素,每个元素大小为size,适合二进制文件、结构体。
  • 示例:读写结构体
    struct stu { char name[20]; int id; float score; }; struct stu s = {"Tom", 1001, 90.5}; // 写 fwrite(&s, sizeof(struct stu), 1, fp); // 读 struct stu s2; fread(&s2, sizeof(struct stu), 1, fp);

3.5 文件定位:fseek/ftell

int fseek(FILE *stream, long offset, int whence); // 移动文件指针 long ftell(FILE *stream); // 获取当前指针位置
  • whence:参考位置
    • SEEK_SET:文件开头
    • SEEK_CUR:当前位置
    • SEEK_END:文件末尾
  • 示例:获取文件大小
    fseek(fp, 0, SEEK_END); // 移到末尾 long size = ftell(fp); // 末尾位置就是文件大小

3.6 标准 IO 缓冲区

标准 IO 自带缓冲区,分为 3 种:

  • 全缓冲:缓冲区满才刷新(普通文件默认)。
  • 行缓冲:遇到\n才刷新(stdout默认)。
  • 无缓冲:立即输出(stderr默认)。
  • 手动刷新:int fflush(FILE *stream);

四、实战:用标准 IO 实现cat命令

cat命令功能:读取文件内容并输出到屏幕。

#include <stdio.h> int main(int argc, char *argv[]) { if (argc != 2) { printf("Usage: %s <filename>\n", argv[0]); return -1; } FILE *fp = fopen(argv[1], "r"); if (fp == NULL) { perror("fopen failed"); return -1; } char buf[1024]; while (fgets(buf, sizeof(buf), fp) != NULL) { fputs(buf, stdout); // 输出到屏幕 } fclose(fp); return 0; }

五、系统 IO(系统调用):更底层的操作

系统 IO 是 Linux 内核提供的原生函数,没有缓冲区,直接操作文件描述符(int fd)。

5.1 文件描述符(fd)

  • 内核为每个打开的文件分配一个整数fd,用来标识文件。
  • 默认打开的 3 个文件描述符:
    • 0:标准输入(stdin
    • 1:标准输出(stdout
    • 2:标准错误(stderr

5.2 核心系统调用

函数功能原型
open打开 / 创建文件int open(const char *pathname, int flags, mode_t mode);
read读文件ssize_t read(int fd, void *buf, size_t count);
write写文件ssize_t write(int fd, const void *buf, size_t count);
lseek移动文件指针off_t lseek(int fd, off_t offset, int whence);
close关闭文件int close(int fd);

5.3 标准 IO vs 系统 IO

特性标准 IO(stdio)系统 IO(syscall)
层级库函数,封装系统调用内核原生函数
缓冲区自带,效率高无,直接读写
可移植性好(跨平台)差(仅 Linux)
灵活性高(可精细控制)

六、总结与学习建议

6.1 核心知识点回顾

  1. Linux 一切皆文件:7 种文件类型,统一操作接口。
  2. 文件操作流程:打开 → 读 / 写 → 关闭。
  3. 标准 IOfopen/fclose/fread/fwrite,自带缓冲区,易用高效。
  4. 系统 IOopen/close/read/write,更底层,直接操作文件描述符。
  5. 流与文件描述符FILE*是标准 IO 的抽象,int fd是系统 IO 的抽象。
http://www.jsqmd.com/news/524851/

相关文章:

  • 食品加工污水厂升级三相分离器优质品牌推荐:反硝化菌、可提升旋流曝气器、好氧菌、射流曝气器、微孔曝气器、微生物菌剂选择指南 - 优质品牌商家
  • 企业网络实战:基于VLAN与单臂路由的多部门互联仿真实验
  • Step3-VL-10B-Base开发环境搭建:从Git克隆到ComfyUI可视化流程
  • 2026年3月常州搬家公司最新推荐:居民搬家、搬厂、设备搬运、同城搬家、溧阳搬家、金坛区搬家、武进搬家、新北区搬家等场景选择指南 - 海棠依旧大
  • MogFace开源模型实战教程:基于ONNX Runtime的跨平台推理加速方案
  • Python海龟绘图动画教程:如何用turtle模块制作颜色变化效果
  • TB6612FNG双路H桥驱动模块在GD32F470上的移植与优化
  • 2026年长沙殡仪服务优质机构推荐:殡葬服务一条龙、殡仪一条龙、白事一条龙、长沙慈恩殡仪服务、人文殡葬服务践行者 - 海棠依旧大
  • 优质三指电爪厂商推荐,多爪柔性夹持技术详解 - 品牌2026
  • 软件测试实验室必看:2023版CMA新规下质量管理体系搭建避坑指南
  • Flightmare点云生成全指南:从森林建模到OMPL路径规划实战
  • StructBERT中文情感模型部署指南:从零开始搭建Web服务
  • Codesys ModbusRTU主站配置全攻略:从添加从站到读写操作详解
  • 可靠伺服电爪厂家甄选,严控生产工艺与精度标准 - 品牌2026
  • 14.微信小程序地理定位功能实战:从授权到LBS逆解析全流程
  • 2026年3月长沙殡仪服务公司最新推荐:殡葬、殡仪、白事一条龙、一站式殡仪服务、殡葬用品批发等领域机构选择指南 - 海棠依旧大
  • 嵌入式C语言为何必须使用/* */注释而非//
  • DCT-Net人像卡通化应用场景:独立游戏开发者角色立绘快速原型设计
  • 2026年上海再生资源回收标杆商家最新推荐:实木地板回收、旧铝合金门窗回收、旧阳光房回收、旧地板回收、二手实木地板回收、二手房地板回收、上海聚木富再生资源回收、规范回收服务新标杆 - 海棠依旧大
  • 企业智脑是噱头?看数谷如何帮珠三角企业重塑神经系统?
  • MySQL 第七天:基础回顾 + 锁机制深度解析(附实战 SQL + 高频面试题)
  • 2026苏浙电商培训优质机构精选指南:杭州电商培训机构哪家正规/杭州电商培训机构哪里多/杭州电商培训机构基地/杭州电商培训机构报名/选择指南 - 优质品牌商家
  • 【AI主动工作系统在小龙虾养殖任务中的应用】
  • 金瀛花客服咨询AI流量赋能,重塑智能体验新标杆 - 王老吉弄
  • 保姆级教程:用LVM给Ubuntu22根目录无损扩容500G(含SSD优化技巧)
  • 2026年哈尔滨净化装饰工程优质企业推荐:P2实验室工程、实验室洁净装修、实验室设计规划、实验室通风改造、实验室气路工程、实验室装修改造、黑龙江志航净化装饰工程、洁净工程专业服务商 - 海棠依旧大
  • 计算机毕业设计:基于Flask与Echarts的动漫数据分析大屏系统 Flask框架 可视化 爬虫 大数据 机器学习 番剧推荐(建议收藏)✅
  • 用Altium Designer搞定晶振Layout:从原理图到3D屏蔽的完整实战流程
  • RAFT与FlowNet:深度学习光流估计的演进与实践
  • Redis 学习总结:List、Pub、Stream 用法与场景实战区分