Linux 系统编程:封装基础文件操作库与理解标准错误流 stderr
在深入 Linux 系统编程时,理解底层的文件 IO 机制至关重要。很多时候,直接使用标准库函数 fopen/fwrite 已经足够,但为了掌握缓冲区和文件描述符的本质,手动封装一个简单的文件操作库是非常好的练习。此外,区分标准输出(stdout)和标准错误流(stderr)在调试和日志记录中的不同行为也是基本功。
1. 封装简单的库
1.1 定义文件结构
我们需要一个结构体来模拟 FILE*,包含刷新标志、文件描述符、缓冲区及读写位置等信息。
#define LINE_SIZE 1024
#define FLUSH_NOW 1 // 立即刷新
#define FLUSH_LINE 2 // 行刷新
#define FLUSH_FULL 4 // 全缓冲
typedef struct _myFILE {
unsigned int flags; // 文件刷新方式
int fileno; // fd
char cache[LINE_SIZE]; // 缓冲区
int cap; // 容量
int pos; // 下次写入的位置
} myFILE;
注意:C 语言创建结构体变量通常需要加 struct 关键字,这里使用 typedef 重命名后可以直接用 myFILE。
1.2 打开文件
打开文件的本质是申请内核资源并返回文件描述符。我们的 my_fopen 需要处理不同的打开模式(读、写、追加)。
myFILE* my_fopen(const char* path, const char* flag) {
int flag1 = 0;
int iscreate = 0;
mode_t mode = ;
((flag, ) == ) {
flag1 = O_RDONLY;
} ((flag, ) == ) {
flag1 = (O_WRONLY | O_CREAT | O_TRUNC);
iscreate = ;
} ((flag, ) == ) {
flag1 = (O_WRONLY | O_CREAT | O_APPEND);
iscreate = ;
}
fd = ;
(iscreate)
fd = open(path, flag1, mode);
fd = open(path, flag1);
(fd < ) ;
myFILE* fp = (myFILE*)((myFILE));
(fp == ) ;
fp->fileno = fd;
fp->flags = FLUSH_LINE;
fp->cap = LINE_SIZE;
fp->pos = ;
fp;
}







