文章目录
- [Linux 文件操作详解:结构、系统调用、权限与实践](#Linux 文件操作详解:结构、系统调用、权限与实践)
-
- 一、为什么说"一切皆文件"
- [二、Linux 文件系统结构详解](#二、Linux 文件系统结构详解)
- [三、文件描述符(File Descriptor)](#三、文件描述符(File Descriptor))
-
- 什么是文件描述符?
- [多个 fd 可指向同一文件?](#多个 fd 可指向同一文件?)
- 四、两种文件操作方式对比
- 五、核心系统调用详解(附实战)
-
- [1. `open` 打开文件](#1.
open
打开文件) - [2. `write` 写入文件](#2.
write
写入文件) - [3. `read` 读取文件](#3.
read
读取文件) - [4. `close` 关闭文件](#4.
close
关闭文件) - [5. `lseek` 移动文件指针](#5.
lseek
移动文件指针) - [6. `ioctl` 设备控制](#6.
ioctl
设备控制)
- [1. `open` 打开文件](#1.
- 六、实战代码示例
-
- [文件复制程序(底层 API)](#文件复制程序(底层 API))
- [七、性能分析:time 命令](#七、性能分析:time 命令)
- 八、总结与建议
- 拓展阅读
Linux 文件操作详解:结构、系统调用、权限与实践
关键词: Linux 文件结构、文件描述符、系统调用、read/write、open/close、权限控制、实战代码
一、为什么说"一切皆文件"
Linux 系统将万物抽象为文件:
- 常规文件(普通文本、二进制)
- 目录(实际上是一个特殊的文件)
- 字符设备与块设备(如串口、硬盘)
- 网络连接(socket)
- 虚拟文件(如
/proc/cpuinfo
)
这种设计让系统 I/O 操作接口极其统一,极大提升了系统的灵活性和可扩展性。
二、Linux 文件系统结构详解
目录 | 功能说明 |
---|---|
/ |
根目录,所有文件系统的起点 |
/root |
超级用户的主目录 |
/bin |
二进制可执行程序,系统启动与常用命令 |
/boot |
启动相关文件,如内核镜像 |
/dev |
设备文件(如 /dev/sda 硬盘) |
/etc |
系统配置文件 |
/home |
普通用户的主目录 |
/lib |
系统核心共享库 |
/usr |
用户程序资源(常被挂载为只读) |
/var |
日志、缓存等可变数据 |
/tmp |
临时文件存储 |
/media |
挂载的 U 盘、光盘等 |
/proc |
虚拟文件系统,内核状态如进程信息 |
⚠️
/dev
、/proc
、/sys
等目录是 Linux 与硬件或内核交互的核心。
三、文件描述符(File Descriptor)
什么是文件描述符?
Linux 使用整数 fd(File Descriptor)标识每一个打开的文件资源:
0
:标准输入(stdin)1
:标准输出(stdout)2
:标准错误(stderr)
每当你调用 open()
打开一个文件时,系统都会返回一个新的最小未使用的文件描述符。
多个 fd 可指向同一文件?
是的。例如:
c
int fd1 = open("file.txt", O_RDONLY);
int fd2 = dup(fd1); // 复制 fd1,两个都指向同一个文件
四、两种文件操作方式对比
操作方式 | 示例函数 | 特点说明 |
---|---|---|
底层系统调用 | open , read , write , close |
精准控制、效率高、无缓冲 |
标准 I/O 函数 | fopen , fread , fprintf |
使用方便、有缓冲区 |
系统调用更适合底层开发(如驱动、内核模块),标准 I/O 适合一般应用程序。
五、核心系统调用详解(附实战)
1. open
打开文件
c
int open(const char *pathname, int flags, mode_t mode);
常用标志位:
O_RDONLY
,O_WRONLY
,O_RDWR
O_CREAT
:文件不存在则创建(需提供权限)O_TRUNC
:清空已有内容O_APPEND
:追加模式O_EXCL
:配合O_CREAT
,文件存在则报错
权限常量:
S_IRUSR
:所有者读权限S_IWUSR
:所有者写权限S_IRWXU
:所有者读写执行权限(如0700
)
示例:
c
int fd = open("data.txt", O_RDWR | O_CREAT, 0644);
2. write
写入文件
c
ssize_t write(int fd, const void *buf, size_t count);
- 成功返回写入字节数,失败返回 -1。
- 从当前文件指针开始写入。
示例:
c
write(fd, "Hello\n", 6);
3. read
读取文件
c
ssize_t read(int fd, void *buf, size_t count);
-
返回值:
-
0:读取的字节数
- =0:文件结束
- <0:读取出错
-
示例:
c
char buf[128];
int len = read(fd, buf, sizeof(buf));
4. close
关闭文件
c
int close(int fd);
- 成功返回 0,失败返回 -1。
- 释放资源,fd 变为无效。
5. lseek
移动文件指针
c
off_t lseek(int fd, off_t offset, int whence);
SEEK_SET
:相对于文件头SEEK_CUR
:相对于当前位置SEEK_END
:相对于文件尾部
应用:
c
lseek(fd, 100, SEEK_SET); // 跳到偏移 100
6. ioctl
设备控制
c
int ioctl(int fd, int cmd, ...);
- 专用于控制设备行为
- 不同设备支持不同的
cmd
- 常用于串口、网络驱动、图形接口等底层控制
六、实战代码示例
文件复制程序(底层 API)
c
int fd_in = open("source.txt", O_RDONLY);
int fd_out = open("dest.txt", O_CREAT | O_WRONLY, 0644);
char buf[1024];
int len;
while ((len = read(fd_in, buf, sizeof(buf))) > 0) {
write(fd_out, buf, len);
}
close(fd_in);
close(fd_out);
七、性能分析:time 命令
bash
time ./copy
输出说明:
real
:总执行时间user
:用户空间耗时sys
:系统调用耗时
I/O 密集型程序,
sys
会占比较高。
八、总结与建议
操作 | 场景建议 |
---|---|
open |
精细控制文件打开方式 |
read /write |
控制读取/写入字节精度 |
lseek |
随机读写或偏移操作 |
ioctl |
驱动开发与设备控制 |
fopen /fread |
高级抽象,适合应用层 |
技巧建议:
- 所有
open()
后的fd
必须在适当时机close()
。 - 处理文件写入建议加
O_APPEND
防止并发写覆盖。 - 出错检查别忘记使用
strerror(errno)
获取具体错误信息。
拓展阅读
dup
/dup2
:复制文件描述符poll
/select
:多路复用mmap
:内存映射文件/proc
虚拟文件系统