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

Linux文件I/O系统调用深度解析


Linux文件I/O系统调用深度解析

一、系统调用基础
  1. 核心概念

    • Linux内核通过系统调用提供用户态程序访问内核功能的接口
    • 无需理解内核实现细节即可使用基础功能(如文件操作)
    • 执行流程:用户态→软中断→内核态处理→返回结果
  2. 文件I/O四大操作

    int open(const char *pathname, int flags);   // 打开文件
    ssize_t read(int fd, void *buf, size_t count);   // 读取数据
    ssize_t write(int fd, const void *buf, size_t count);  // 写入数据
    int close(int fd);   // 关闭文件
    

二、open()函数详解

参数说明

// pathname: 文件路径(支持绝对/相对路径)
// flags: 打开模式(位掩码组合)

标志位解析

类别标志位功能
必选O_RDONLY只读模式
O_WRONLY只写模式
O_RDWR读写模式
可选O_CREAT文件不存在时自动创建
O_TRUNC打开时清空文件内容
O_APPEND追加模式(防覆盖)

返回值

  • 成功:返回最小可用文件描述符(≥3,0/1/2被标准流占用)
  • 失败:返回-1(需配合错误处理)

三、关键操作函数
  1. read()数据读取

    ssize_t read(int fd, void *buf, size_t count);
    // 返回实际读取字节数,0表示EOF,-1表示错误
    
  2. write()数据写入

    ssize_t write(int fd, const void *buf, size_t count);
    // 返回实际写入字节数(可能小于count)
    
  3. lseek()文件定位

    off_t lseek(int fd, off_t offset, int whence);
    // whence: SEEK_SET(文件头)/SEEK_CUR(当前位置)/SEEK_END(文件尾)
    

四、错误处理机制
  1. errno全局变量

    #include <errno.h>
    extern int errno;  // 存储最近系统调用的错误码
    
  2. 错误信息转换

    // 方法1:获取错误描述字符串
    char *strerror(int errnum); // 方法2:直接打印错误信息
    perror("open");  // 输出示例:open: No such file or directory
    
  3. 注意事项

    • 错误码仅在函数返回失败时有效
    • 非常规错误:EINTR(系统调用被信号中断)
    • 必须检查每个系统调用的返回值

五、实战代码示例
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>int main() {int fd = open("data.log", O_RDWR | O_CREAT, 0644);if (fd == -1) {perror("文件打开失败");return 1;}// 写入数据char msg[] = "Hello System Call";if (write(fd, msg, sizeof(msg)) == -1) {perror("写入失败");close(fd);return 1;}// 重置文件指针到开头lseek(fd, 0, SEEK_SET);// 读取数据char buf[100];ssize_t bytes = read(fd, buf, sizeof(buf));if (bytes > 0) {printf("读取内容: %.*s\n", (int)bytes, buf);}close(fd);return 0;
}

六、技术要点总结
特性说明
文件描述符重用关闭文件后描述符可被新文件复用
原子操作`O_CREAT
内核缓冲区write() 数据先写入内核缓冲区,由系统决定同步到磁盘的时间
标准文件描述符0(stdin), 1(stdout), 2(stderr) 在进程启动时自动打开

扩展知识

  • 文件描述符表与进程关系
  • 非阻塞I/O(O_NONBLOCK标志)
  • 文件锁机制(fcntl()函数)

原创技术笔记,转载需注明出处。更多系统编程内容持续更新中…

http://www.lryc.cn/news/572309.html

相关文章:

  • C++ 面向对象特性详解:继承机制
  • 【AI作画】第2章comfy ui的一般输入节点,文本框的类型和输入形式
  • F接口基础.go
  • P2066 机器分配
  • 八字排盘小游戏微信流量主小程序开源
  • 【嵌入式硬件实例】-555定时器控制舵机/伺服电机
  • 坤驰科技QTS4200战鹰(Battle Eagle)系列实时频谱分析记录回放系统
  • day09——Java基础项目(ATM系统)
  • AI免费工具:promptpilot、今天学点啥、中英文翻译
  • HarmonyOS性能优化——并发能力使用
  • ULS23 挑战:用于计算机断层扫描中 3D 通用病变分割的基准模型及基准数据集|文献速递-深度学习医疗AI最新文献
  • 国产USRP X440 PRO:超大带宽、多通道相参同步的旗舰型软件无线电设备
  • 高密度HDI板与普通pcb有什么区别?
  • Singularity 安装
  • Postman 的 Jenkins 管理 - 手动构建
  • Burp suite2024+新版本中英文等宽字体设置让其更美观显示
  • 额度互动促进金融健康,蚂蚁消金创新智能实时交互式风控系统
  • 【深度学习:进阶篇】--3.2.经典分类网络结构(CNN)
  • Stroke-based Cyclic Amplifier (SbCA方法):实现图像任意尺度超清放大
  • 端口安全配置示例
  • 安卓JetPack篇——LifeCycle原理
  • flink如何基于Pekko实现RPC调用
  • 神经网络试题
  • DL___线性神经网络
  • 数据结构 二叉树理论、递归理论与快速排序理论 6.19
  • 01.线性代数是如何将复杂的数据结构转化为可计算的数学问题,这个过程是如何进行的
  • OpenAI的Prompt工程
  • 03.自动特征提取(深度学习)核心逻辑:通过多层非线性变换,让模型自动学习从原始数据到高层特征的映射。为什么多层非线性变换可以达到这样的效果?
  • 【LINUX网络】网络socet接口的基本使用以及实现简易UDP通信
  • Linux内存进阶