Linux 文件操作详解:结构、系统调用、权限与实践
文章目录
- Linux 文件操作详解:结构、系统调用、权限与实践
- 一、为什么说“一切皆文件”
- 二、Linux 文件系统结构详解
- 三、文件描述符(File Descriptor)
- 什么是文件描述符?
- 多个 fd 可指向同一文件?
- 四、两种文件操作方式对比
- 五、核心系统调用详解(附实战)
- 1. `open` 打开文件
- 2. `write` 写入文件
- 3. `read` 读取文件
- 4. `close` 关闭文件
- 5. `lseek` 移动文件指针
- 6. `ioctl` 设备控制
- 六、实战代码示例
- 文件复制程序(底层 API)
- 七、性能分析: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 可指向同一文件?
是的。例如:
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
打开文件
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
)
示例:
int fd = open("data.txt", O_RDWR | O_CREAT, 0644);
2. write
写入文件
ssize_t write(int fd, const void *buf, size_t count);
- 成功返回写入字节数,失败返回 -1。
- 从当前文件指针开始写入。
示例:
write(fd, "Hello\n", 6);
3. read
读取文件
ssize_t read(int fd, void *buf, size_t count);
-
返回值:
-
0:读取的字节数
- =0:文件结束
- <0:读取出错
-
示例:
char buf[128];
int len = read(fd, buf, sizeof(buf));
4. close
关闭文件
int close(int fd);
- 成功返回 0,失败返回 -1。
- 释放资源,fd 变为无效。
5. lseek
移动文件指针
off_t lseek(int fd, off_t offset, int whence);
SEEK_SET
:相对于文件头SEEK_CUR
:相对于当前位置SEEK_END
:相对于文件尾部
应用:
lseek(fd, 100, SEEK_SET); // 跳到偏移 100
6. ioctl
设备控制
int ioctl(int fd, int cmd, ...);
- 专用于控制设备行为
- 不同设备支持不同的
cmd
- 常用于串口、网络驱动、图形接口等底层控制
六、实战代码示例
文件复制程序(底层 API)
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 命令
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
虚拟文件系统