Linux文件I/O操作全解析
文件I/O:Linux内核提供得文件操作相关接口
1. 打开文件 open
2. 读、写文件 read/write
3. 关闭文件 close
一、函数接口
1.open函数
函数原型:int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
需要的头文件:
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>
功能:打开一个文件并获得一个文件描述符
参数:
参数类型 | 参数 | 参数说明 |
char * | pathname | 指定要打开或者创建的文件路径(绝对/相对路径) |
int | flags | 指定文件的打开方式和行为 |
mode_t | mode | 文件操作权限(读写执行) flags中有O_CREAT标注位时,在创建文件时必须要有mode参数 权限值由八进制表示, rwxrwxrwx---->0777 rw-rw-r-- ------>0664 |
flags: 打开方式
O_RDONLY | 以只读得方式打开 |
O_WRONLY | 以只写得方式打开 |
O_RDWR | 以可读可写的方式打开 |
O_CREAT | 若文件不存在,则创建 0664 |
O_TRUNC | 若文件存在且可写,打开时清空文件内容 |
O_APPEND | 追加写 |
标准IO与文件IO打开方式对比:
标准IO | 文件IO | |
"r" | O_RDONLY | 以只读得方式打开 |
"r+" | O_RDWR | 以读写的方式打开 |
"w" | O_WRONLY | O_TRUNC | O_CREAT, 0664 | |
"w+" | O_RDWR | O_TRUNC | O_CREAT, 0664 | |
"a" | O_WRONLY | O_APPEND | O_CREAT, 0664 | |
"a+" | O_RDWR | O_APPEND | O_CREAT, 0664 |
返回值:
成功 | 返回一个文件描述符(非负整数) |
失败 | -1 |
文件描述符:操作系统中已打开文件的标识符
小的,非负的整型数据
范围:0 - 1023(总共1024个)
分配原则:最小位被使用原则
系统默认已经打开的文件描述符
标准IO:FILE | 文件IO:int | |
stdin | 0 | 标准输入 |
stdout | 1 | 标准输出 |
stderr | 2 | 标准出错 |
2. close函数
函数原型:int close(int fd);
需要的头文件:#include<unisted.h>
功能:关闭文件
参数:
fd | 需要关闭的文件描述符 |
返回值:
成功 | 0 |
失败 | -1 |
文件描述符泄漏:程序打开文件后,未通过close函数正确释放文件描述符,导致其长期占用系统资源的现象。
3.write函数
函数原型:ssize_t write(int fd, const void *buf, size_t count);
需要的头文件:#include <unistd.h>
功能:向文件中写入数据
参数:
fd | 要写入的文件的文件描述符 |
buf | 要写入的内容的首地址 |
count | 要写的字节数 |
返回值:
成功 | 实际写入的字节数 |
失败 | -1 |
4.read函数
函数原型:ssize_t read(int fd, void *buf, size_t count);
需要的头文件:#include <unistd.h>
功能:从文件中读取数据
参数:
fd | 要读取的文件的文件描述符 |
buf | 存放读取的数据的首地址 |
count | 希望从文件中读到的字节数 |
返回值:
成功 | 实际读到的字节数 |
文件末尾 | 0 |
失败 | -1 |
练习:
使用read将stdio.h文件中的内容打印到终端。
5.lessk函数
函数原型:off_t lseek(int fd, off_t offset, int whence);
需要的头文件:#include <sys/types.h> #include <unistd.h>
功能:文件读写位置定位
参数:
fd | 文件描述符 |
offset | 偏移量(字节) |
whence |
返回值:
练习:求文件大小
标准IO:属于C库函数 | 文件IO:属于系统调用 |
标准IO是系统调用的一次封装,增加了缓冲区,目的是提高数据读写的效率; 移植性强 | 文件IO无缓冲区 文件 IO主要应用在对硬件的操作,也可以操作普通文件 只能用于Linux操作系统,移植性弱 |
缓冲区
在C语言中,缓冲区(Buffer) 是内存中一块临时存储数据的区域,用于协调数据输入/输出(I/O)的速度差异,比如程序与外部设备(键盘、显示器、文件等)之间的速度不匹配。
缓冲区的作用
提高效率:减少直接与外部设备的交互次数。例如,向文件写入数据时,先将数据暂存到缓冲区,积累到一定量再一次性写入文件,比每次写一个字符更高效。
平滑数据传输:当设备处理速度慢于程序输出速度(或快于程序输入速度)时,缓冲区可临时存储数据,避免程序等待。
在C语言中,标准I/O函数(如printf、scanf、fprintf等)默认使用缓冲区,主要分为以下3类:
1.行缓冲 1k(1024字节)--------》人机交互界面、终端
行缓冲区被刷新的方法:
1.程序结束,自动刷新缓冲区
2.遇到\n刷新
3.fflush(强制刷新)
4.缓冲区满刷新
例如:printf("hello"); 可能不会立即显示,而 printf("hello\n"); 会因\n触发缓冲区刷新,立即显示。
2.全缓冲 4k(4096字节)--------》文件缓冲区,当缓冲区被填满时才执行实际I/O操作。常见于对文件的操作
缓冲区被刷新的方法:
1.程序结束,自动刷新缓冲区
2.fflush()(强制刷新)
3.文件关闭刷新
4.缓冲区满刷新
3.无缓冲 0k-------------》出错信息对应的设备,数据不经过缓冲区,直接进行I/O操作。常见于标准错误输出(stderr),确保错误信息能及时显示。
stderr----》无缓存
作业
编写日志模块:
log:记录系统运行过程的一些信息。
1.记录调试信息
2.记录运行参数
3.记录出错信息
要求:1.以文件方式保存信息(一天保存一个日志文件)
2.文件名字如下:20250812.log
日志文件保存格式如下:
[2025-08-12 17:09:23][日志等级]日志信息!
[2025-08-12 17:09:23][ERROR]打开文件失败!
[2025-08-12 17:09:23][WARNING]***模块重新启动!
日志等级:
ERROR:表示严重错误
WARNING:对系统不会产生严重问题的警告信息
INFO:调试信息
3.封装以下函数完成:
int init_log(); 功能:在系统运行之初,创建并打开日志文件