面试题答案
一键面试C语言标准库文件输入输出函数实现机制
- 缓冲区管理:
- C标准库的文件I/O函数(如
fopen
、fread
、fwrite
等)通常使用缓冲区来减少系统调用的次数。分为全缓冲、行缓冲和无缓冲。- 全缓冲:当缓冲区被填满时,才会执行实际的I/O操作。对于磁盘文件通常是全缓冲,标准库会为每个打开的文件分配一个缓冲区(大小一般为4096字节或8192字节等)。例如
fwrite
函数向缓冲区写入数据,当缓冲区满时,通过系统调用将缓冲区数据写入文件。 - 行缓冲:当遇到换行符
\n
或缓冲区满时,执行I/O操作。常用于终端设备,如stdout
。 - 无缓冲:数据直接被写入或读出,不经过缓冲区,
stderr
通常是无缓冲的。
- 全缓冲:当缓冲区被填满时,才会执行实际的I/O操作。对于磁盘文件通常是全缓冲,标准库会为每个打开的文件分配一个缓冲区(大小一般为4096字节或8192字节等)。例如
- C标准库的文件I/O函数(如
- 系统调用:
- 在Linux系统中,底层系统调用主要是
open
、read
、write
、close
等。例如fopen
函数在内部调用open
系统调用来打开文件,获取文件描述符。fread
和fwrite
函数在缓冲区操作后,当需要真正读写数据时,会调用read
和write
系统调用。fclose
函数则调用close
系统调用来关闭文件。
- 在Linux系统中,底层系统调用主要是
自定义文件输入输出函数库设计思路
- 更灵活的缓冲区控制:
- 允许用户在打开文件时指定缓冲区大小,而不是使用固定的默认值。
- 提供函数来手动刷新缓冲区,而不仅仅依赖于缓冲区满或特定条件触发的自动刷新。
- 异步I/O能力:
- 使用操作系统提供的异步I/O机制,如Linux的
aio_read
和aio_write
函数。 - 引入回调机制,当异步I/O操作完成时,调用用户指定的回调函数。
- 使用操作系统提供的异步I/O机制,如Linux的
关键代码实现
- 自定义文件结构体:
typedef struct {
int fd; // 文件描述符
char *buffer; // 缓冲区
size_t buffer_size; // 缓冲区大小
size_t buffer_pos; // 当前缓冲区位置
int is_async; // 是否异步
void (*callback)(void *); // 异步回调函数
void *callback_arg; // 回调函数参数
} my_file;
- 自定义打开文件函数:
my_file* my_fopen(const char *path, const char *mode, size_t buffer_size, int is_async, void (*callback)(void *), void *callback_arg) {
int fd = open(path, mode == "r"? O_RDONLY : mode == "w"? O_WRONLY | O_CREAT | O_TRUNC : -1, 0666);
if (fd == -1) {
return NULL;
}
my_file *file = (my_file*)malloc(sizeof(my_file));
file->fd = fd;
file->buffer = (char*)malloc(buffer_size);
file->buffer_size = buffer_size;
file->buffer_pos = 0;
file->is_async = is_async;
file->callback = callback;
file->callback_arg = callback_arg;
return file;
}
- 自定义写入函数(同步部分):
size_t my_fwrite(const void *ptr, size_t size, size_t nmemb, my_file *file) {
size_t total_size = size * nmemb;
size_t remaining = total_size;
while (remaining > 0) {
size_t to_write = remaining > (file->buffer_size - file->buffer_pos)? (file->buffer_size - file->buffer_pos) : remaining;
memcpy(file->buffer + file->buffer_pos, ptr, to_write);
file->buffer_pos += to_write;
ptr += to_write;
remaining -= to_write;
if (file->buffer_pos == file->buffer_size) {
if (write(file->fd, file->buffer, file->buffer_size) == -1) {
// 错误处理
return 0;
}
file->buffer_pos = 0;
}
}
return total_size;
}
- 自定义写入函数(异步部分):
void my_fwrite_async(const void *ptr, size_t size, size_t nmemb, my_file *file) {
struct aiocb aiocbp;
memset(&aiocbp, 0, sizeof(struct aiocb));
aiocbp.aio_fildes = file->fd;
aiocbp.aio_buf = (void *)ptr;
aiocbp.aio_nbytes = size * nmemb;
aiocbp.aio_offset = 0;
aiocbp.aio_sigevent.sigev_notify = SIGEV_THREAD;
aiocbp.aio_sigevent.sigev_notify_function = file->callback;
aiocbp.aio_sigevent.sigev_value.sival_ptr = file->callback_arg;
if (aio_write(&aiocbp) == -1) {
// 错误处理
}
}
- 自定义关闭文件函数:
int my_fclose(my_file *file) {
if (file->buffer_pos > 0) {
if (write(file->fd, file->buffer, file->buffer_pos) == -1) {
// 错误处理
free(file->buffer);
close(file->fd);
free(file);
return -1;
}
}
free(file->buffer);
close(file->fd);
free(file);
return 0;
}
以上代码仅为关键部分示例,实际使用中还需要完善错误处理等细节。