AI课堂行为分析系统:从计算机视觉到多模态融合的工程实践
2026/7/5 17:30:46
在 Linux 中操作文件有两种核心方式:文件 IO(系统调用)和标准 IO(C 库函数),二者底层关联但适用场景不同。
| 类型 | 本质 | 核心特征 | 适用场景 |
|---|---|---|---|
| 文件 IO | 操作系统对外提供的系统调用函数 | 无缓冲区、文件描述符(int)、功能强大 | 设备文件(如/dev下设备)、实时性要求高的场景 |
| 标准 IO | C 标准库封装的文件操作函数 | 带缓冲区、文件流指针(FILE*)、跨平台 | 普通文件(文本 / 二进制)、通用文件操作 |
| 维度 | 共同点 | 区别 |
|---|---|---|
| 核心目标 | 均用于文件读写操作 | 文件 IO:无缓存、fd、系统调用;标准 IO:有缓存、FILE*、C 库封装 |
| 跨平台性 | - | 文件 IO:依赖具体系统(如 Linux);标准 IO:跨平台(Windows/Linux 通用) |
| 效率 | - | 普通文件:标准 IO 更高(缓存);设备文件:文件 IO 更优(实时) |
文件 IO 的操作流程遵循 “打开→读写→关闭” 的固定范式,核心依赖open/read/write/close四个系统调用。
c
运行
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open(const char *pathname, int flags, mode_t mode);| 参数 | 说明 | 常用取值 |
|---|---|---|
| pathname | 文件路径(绝对 / 相对路径) | "1.txt"、"/etc/passwd" |
| flags | 打开模式(必选 + 可选组合) | 必选:O_RDONLY(只读)、O_WRONLY(只写)、O_RDWR(读写)可选:O_CREAT(创建文件)、O_TRUNC(清空文件)、O_APPEND(追加写) |
| mode | 文件权限(仅O_CREAT时有效) | 0666(读写权限)、0777(读写执行权限) |
perror查看错误原因)。c
运行
// 以只写+创建+清空模式打开1.txt,权限0666 int fd = open("1.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd == -1) { perror("open failed"); return 1; }c
运行
#include <unistd.h> ssize_t read(int fd, void *buf, size_t count);| 参数 | 说明 |
|---|---|
| fd | 目标文件的文件描述符(open 返回值) |
| buf | 接收数据的内存缓冲区(需提前分配空间) |
| count | 本次读取的最大字节数(建议大于文件实际大小) |
0:实际读取到的字节数;
c
运行
char buf[1024] = {0}; // 从fd读取最多1024字节到buf ssize_t n = read(fd, buf, sizeof(buf)); if (n < 0) { perror("read failed"); close(fd); return 1; } printf("读取到%d字节:%s\n", n, buf);c
运行
#include <unistd.h> ssize_t write(int fd, const void *buf, size_t count);| 参数 | 说明 |
|---|---|
| fd | 目标文件的文件描述符 |
| buf | 待写入文件的数据缓冲区 |
| count | 待写入数据的有效长度(如strlen(buf)) |
0:实际写入的字节数;
c
运行
char *data = "Hello Linux File IO!"; // 写入data到fd,长度为字符串有效长度 ssize_t n = write(fd, data, strlen(data)); if (n < 0) { perror("write failed"); close(fd); return 1; } printf("写入%d字节\n", n);c
运行
#include <unistd.h> int close(int fd);c
运行
if (close(fd) == -1) { perror("close failed"); return 1; }除了普通文件,Linux 中目录也是一种特殊文件,需通过专门的函数操作,流程为 “打开目录→读取目录→关闭目录”。
c
运行
#include <dirent.h> DIR *opendir(const char *name);name为目录路径(如"."、"/home");DIR*(目录流指针),失败返回 NULL。c
运行
#include <dirent.h> struct dirent *readdir(DIR *dirp);dirp为opendir返回的目录流指针;struct dirent*(包含文件名、文件类型等信息);c
运行
struct dirent { ino_t d_ino; // 索引节点号 char d_name[256]; // 文件名(核心字段) // 其他字段:文件类型、偏移量等 };c
运行
#include <dirent.h> int closedir(DIR *dirp);c
运行
#include <stdio.h> #include <dirent.h> int main() { // 打开当前目录 DIR *dir = opendir("."); if (dir == NULL) { perror("opendir failed"); return 1; } // 遍历目录中的文件 struct dirent *entry; while ((entry = readdir(dir)) != NULL) { printf("文件名:%s\n", entry->d_name); } // 关闭目录 closedir(dir); return 0; }当工程包含多个源文件时,手动执行gcc编译效率极低,Makefile 可实现 “一键编译”,自动管理编译依赖和规则。
make命令时,系统会查找当前目录的makefile/Makefile文件并执行;目标:依赖\n\t规则(TAB 缩进是关键,不能用空格);a.out)或操作(如clean);main.c、func.c);gcc main.c func.c -o a.out)。makefile
# 目标:a.out;依赖:main.c、func.c a.out:main.c func.c gcc main.c func.c -o a.out # 无依赖的目标(清理编译产物) clean: rm -f a.outmake:编译生成a.out(仅当依赖文件修改时重新编译);make clean:删除a.out;Makefile 提供内置变量简化编写,核心内置变量:
$^:当前规则的所有依赖文件;$@:当前规则的目标文件。makefile
a.out:main.c func.c gcc $^ -o $@ # 等价于 gcc main.c func.c -o a.out clean: rm -f $@ # 等价于 rm -f a.out通过自定义变量适配不同工程,可灵活修改源文件、目标名、编译选项:
makefile
# 自定义变量:源文件、目标名、编译选项 SRC = main.c SRC += func.c # 追加源文件 APP = a.out FLAG = -g # 编译调试信息 # 规则:依赖为SRC,目标为APP $(APP):$(SRC) gcc $^ -o $@ $(FLAG) # 加入编译选项 # 清理规则 clean: rm -f $(APP)main.c)修改时,才重新编译生成目标(a.out),未修改则提示is up to date;all、clean、install),执行make 目标名即可触发对应规则;c
运行
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <string.h> int main() { // 1. 打开文件 int fd = open("test.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd == -1) { perror("open failed"); return 1; } // 2. 写入文件 char *data = "Hello File IO!\n"; write(fd, data, strlen(data)); // 3. 关闭文件 close(fd); // 重新打开读取 fd = open("test.txt", O_RDONLY); if (fd == -1) { perror("open failed"); return 1; } char buf[1024] = {0}; read(fd, buf, sizeof(buf)); printf("读取内容:%s", buf); close(fd); return 0; }makefile
SRC = main.c APP = file_io_demo FLAG = -g $(APP):$(SRC) gcc $^ -o $@ $(FLAG) clean: rm -f $(APP) test.txtbash
运行
# 编译 make # 运行 ./file_io_demo # 清理 make clean