【Linux操作系统】简学深悟启示录:文件fd
文章目录
- 1.前言
- 2.C文件接口回顾
- 3.stdin & stdout & stderr
- 4.系统文件调用
- 4.1 open
- 4.2 write
- 5.访问文件本质
- 希望读者们多多三连支持
- 小编会继续更新
- 你们的鼓励就是我前进的动力!
1.前言
有些东西作为共识原理,我们都要知道,知道我们学习文件到底是在学什么?
- 文件 = 内容 + 属性
- 文件分为打开的文件和没打开的文件
- 已打开的文件本质就是在研究文件和进程的关系
- 没打开的文件一般存放在磁盘上,我们最关心什么问题?系统是怎么管理文件的?如何先描述再组织的?重定向和缓冲区的本质?
2.C文件接口回顾
以上代码将会对 C
文件相关的函数使用细节进行回顾,但是具体的函数使用就不回顾了,可自行查询学习
fopen
以写方式打开 log.txt
文件,fwrite
将 str
写入 fp
文件,注意会以二进制写入,所以要符合字符编码,尽量以字符串写入,最后 fclose
关闭文件。运行代码可以发现确实多了一个 log.txt
的文件,该文件创建在与代码编译文件同一目录下,这是默认路径的结果,有没有什么办法改变默认路径呢?
chdir(/home/zzh_test);
chdir
是一种用于修改当前进程工作目录的函数,将这一行代码添加到 main
函数最前面,然后要在 fwrite
后加个 sleep(1000)
用于暂停观察进程状态,还要加个 fflush(fp)
刷新缓冲区(原因后面会讲)
可以看到文件的路径确实被修改了,能够在 /home/zzh_test
路径下被找到
我们修改 fwrite
之后再次打开文件发现之前内容消失了,这是因为 w
方式打开的文件会清空文件,想要添加内容应该用 a
方式打开
还有很多 C
文件函数就不赘述了~
3.stdin & stdout & stderr
在系统中有三个输入输出流会被默认打开,分别是 stdin
(键盘输入)、stdout
(显示器输出)、stderr
(显示器输出错误信息)
这三个输入输出流分别对应 0
、1
、2
的文件描述符,文件描述符可以理解为一种问津标签,这三个输入输出流分别独立互不影响
例如 fprintf(stdout,"hello world")
表示向显示器打印,等价于 printf("hello world")
4.系统文件调用
文件是存在于磁盘上的,访问文件就是访问磁盘,也就是访问硬件,也就是通过代码访问硬件,必定是要经过操作系统的接口的。我们所学的 C
文件函数其实都是封装了系统文件的
4.1 open
我们这里介绍下面这条函数:
pathname:要打开或创建的目标文件
flags:打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行 或运算
构成 flags
#include <stdio.h>
#include <unistd.h>
#include <string.h>#define ONE (1<<0) // 1
#define TWO (1<<1) // 2
#define THREE (1<<2) // 4
#define FOUR (1<<3) // 8void show(int flags)
{if(flags&ONE) printf("hello function1\n");if(flags&TWO) printf("hello function2\n");if(flags&THREE) printf("hello function3\n");if(flags&FOUR) printf("hello function4\n");
}int main()
{show(ONE);show(TWO);show(ONE|TWO);show(ONE|TWO|THREE);return 0;
}
系统里对于 flags
多个选项组合使用多个功能又互不影响,使用的是以上类似的代码
如果 flags
是 ONE | TWO(0001 | 0010 = 0011)
,那么 flags & ONE(0011 & 0001 = 0001)
和 flags & TWO(0011 & 0010 = 0010)
都会非 0
,所以会同时打印 hello function1
和 hello function2
flags 参数:
- 打开方式标志(必选其一,且只能选一个),常用取值:
O_RDONLY
:只读模式
O_WRONLY
:只写模式
O_RDWR
:读写模式 - 可组合的附加标志(用
|
连接):
O_CREAT
:若文件不存在则创建
O_TRUNC
:打开文件时清空原有内容
O_APPEND
:追加模式(写入内容到文件末尾)
O_EXCL
:与O_CREAT
一起使用,若文件已存在则报错
mode:当使用 O_CREAT
时,需指定新文件的权限(如 0644
),否则可省略
返回值: 文件描述符
4.2 write
write
的使用和 fwrite
差不多,不过是把目标文件改成文件描述符,返回的是写入的字符个数
使用示例如下:
5.访问文件本质
上面我们多次提到文件描述符,这到底是什么?又有什么用呢?
内存中的 PCB
,即 task_struct
,内部有个 struct files_struct* files
指针,指向一个 struct files_struct
结构体,里面包含了一个 struct file *fd_array[]
,这个数组就叫文件描述符表,该数组的每个下标就是一个 fd
,存储了各个文件存储的地址,fd
相当于文件的标志,这些文件通常是 struct file
,描述了一个被打开文件的信息
🔥值得注意的是:
- 在
struct file
中文件描述符为fileno
FILE
的本质就是封装了fd
的结果- 文件会尽量往文件描述符表低位存储,即使
stdout
关闭显示器输出,也不会影响stderr
,因为他们两是独立开来的