文件IO
文件IO系统调用
文件标准库函数和系统调用的关系
fopen(3)
调用open(2)打开指定的文件(从系统调用开始),返回一个文件描述符(就是一个int类型的编号),分配一个FILE结构体(FILE *),其中包含该文件的描述符、I/O缓冲区(一个指针记录buffer位置)和当前读写位置等信息,返回这个FILE结构体的地址。
C标准I/O库函数(fopen,fclose,fputc,fgetc,fprintf,fscanf…)的运行空间是用户空间。
fgetc(3)
通过传入的FILE *参数找到该文件的描述符、I/O缓冲区和当前读写位置,判断能否冲I/O缓冲区中读到下一个字符,如果能读到就直接返回该字符,否则调用read(2),把文件描述符传进去,让内核读取该文件的数据到I/O缓冲区,然后返回下一个字符。
fputc(3)
判断该文件的I/O缓冲区是否有空间再存放一个字符,如果有空间则直接保存在I/O缓冲区中并返回,如果I/O缓冲区已满就调用write(2),让内核把I/O缓冲区的内容写回文件。
fclose(3)
如果I/O缓冲区中还有数据没写回文件,就调用write(2)写回文件,然后调用close(2)关闭文件,释放FILE结构体和I/O缓冲区。
C标准库的缓冲区分类
缓冲区的本质是一片存储区域。
- 全缓冲:缓冲区被填满时,才真正的触发系统调用。
- 行缓冲:当出现换行时,立刻调用系统调用,把数据交给内核操作,标准输入输出都是行缓冲。
- 无缓冲:缓冲区接收一个数据接进行一次系统调用。
行缓冲
/*************************************************************************
> File Name: hello.c
> Author:
> Mail:
> Created Time: Fri 25 Feb 2022 12:31:51 PM CST
************************************************************************/
#include<stdio.h>
int main() {
fputc('Y', stdout); //stdout 为标准输出 为行缓冲
//fputc('Y', stderr); //stdout 为无缓冲
//fputc('\n', stdout); //遇到换行时输出Y
while(1) {
;
}
return 0;
}
没有遇到换行时没有任何输出。
遇到换行时输出Y
open创建文件
open
open函数可以打开或创建一个文件。
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
返回值:成功返回新分配的文件描述符,出错返回-1并设置errno。
pathname参数时要打开或创建的文件名,既可以是相对路径也可以是绝对路径。
flags参数有一系列常熟指可供选择,可以同时选择多个常数用按位或运算符连接起来,所以这些常数的宏定义都以0_开头,表示or。
必选项:以下三个常数中必须指定一个,且仅允许指定一个。
O_RDONLY 只读打开
O_WRONLY 只写打开
O_RDWR 可写可读打开
可选项:可以同时指定0个或多个,和必选项按位或起来作为flags参数。
O_CREAT 若此文件不存在则创建它。必需要提供第三个参数mode,表示文件的访问权限。
O_EXCL 如果同时指定了O_CREAT,并且文件已存在,则返回出错。
O_TRUNC 如果文件已存在,并且以只写或可读可写方式打开,则将其长度截断为0字节。
O_APPEND 表示追加。如果文件已有内容,这次打开文件所写的数据附加到文件的末尾。
O_NONBLOCK 对于设备文件,以O_NONBLOCK方式打