Linux文件I/O系统调用深度解析
Linux文件I/O系统调用深度解析
一、系统调用基础
-
核心概念
- Linux内核通过系统调用提供用户态程序访问内核功能的接口
- 无需理解内核实现细节即可使用基础功能(如文件操作)
- 执行流程:用户态→软中断→内核态处理→返回结果
-
文件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(需配合错误处理)
三、关键操作函数
-
read()数据读取
ssize_t read(int fd, void *buf, size_t count); // 返回实际读取字节数,0表示EOF,-1表示错误
-
write()数据写入
ssize_t write(int fd, const void *buf, size_t count); // 返回实际写入字节数(可能小于count)
-
lseek()文件定位
off_t lseek(int fd, off_t offset, int whence); // whence: SEEK_SET(文件头)/SEEK_CUR(当前位置)/SEEK_END(文件尾)
四、错误处理机制
-
errno全局变量
#include <errno.h> extern int errno; // 存储最近系统调用的错误码
-
错误信息转换
// 方法1:获取错误描述字符串 char *strerror(int errnum); // 方法2:直接打印错误信息 perror("open"); // 输出示例:open: No such file or directory
-
注意事项
- 错误码仅在函数返回失败时有效
- 非常规错误:
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()
函数)
原创技术笔记,转载需注明出处。更多系统编程内容持续更新中…