由前面的文件的讲解可知,文件描述符就是一个小整数。
0 & 1& 2
任何程序在运行时都会变成进程,C标准库都会默认为其打开三个输入输出流:stdin,stdout,stderr。这三个流的类型都是FILE*,fopen 的返回值类型也是文件指针。
名字 | 对应设备 | 对应文件描述符 |
---|---|---|
stdin:标准输入 | 键盘 | 0 |
stdout:标准输出 | 显示器 | 1 |
stderr:标准错误 | 显示器 | 2 |
所以输入输出时还可以采用如下方式:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main()
{
char buf[1024];
ssize_t s=read(0,buf,sizeof(buf)); //即从标准输入(键盘)上读取数据
if(s>0)
{
buf[s]=0;
write(1,buf,strlen(buf)); //向标准输出(显示器)中写入数据
write(2,buf,strlen(buf)); //向标准错误(显示器)中写入数据
}
return 0;
}
而现在我们知道,文件描述符就是从0 开始的小整数。当我们打开文件时,操作系统在内存中要创建相应的数据结构来描述目标文件。于是就有了file结构体,用来表示一个已经打开的文件对象。
而进程要执行open系统调用,必须让进程和文件关联起来。即需要每个进程有一个* files 指针指向一张files_struct,该表中最重要的部分就是包含了一个指针数组,每个元素都是一个指向已打开文件的指针。所以文件指针(FILE*)与文件描述符(fd[])的作用相同,都是用来标识唯一的一个文件。
故本质上,文件描述符就是进程中指针数组的下标。
如下图所示:我们只要有文件描述符,就可以找到相应的文件及其信息
文件描述符的分配规则
直接看代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int fd=open("newfile",O_RDONLY|O_CREAT);
if(fd<0)
{
perror("open");
return 1;
}
printf("fd:%d\n",fd);
close(fd);
return 0;
}
我们关闭0或2,再观察一下:
由此我们猜想文件描述符的分配规则是:在file_struct 数组中,找到当前没有被使用的最小的一个下标,作为新的文件描述符。
文件系统
文件系统用于管理磁盘上的文件,文件=文件名+文件内容+文件属性
1. 查看文件:
ls -l
每个文件包含7个信息:模式、硬链接数、文件所有者、文件所属组、大小、最后修改时间、文件名
stat filename
可以看到每个文件的详细信息(包括 inode,link)
在上面的执行结果中,我们有几个重要的信息需要解释:inode 和 硬链接
2. inode
inode 的作用相当于进程中的PCB用于描述文件,而inode号相当于pid 用于标识/组织文件。
思考:
在OS中,已经有文件描述符用于唯一标识文件,为什么还需要inode去标识文件?
因为计算机本质是为人提供服务的,所以我们需要文件描述符去方便用户查找文件,但是OS在磁盘使用inode会更方便运作。因此二者并不冲突,就好像我们在学校里的时候,老师喜欢用学号唯一标识我们,而不是用身份证号管理我们大家。
1)超级块:总纲,用于存放文件系统本身的结构信息
2)inode 位图:每个bit 位表示一个inode 是否空闲可用。
创建文件
- 通过inode 位图找到空闲的 i 节点,内核把文件信息记录其中。
- 确定文件需要的数据块数,内核找到空闲块,将缓冲内容依次复制
- 文件内容按顺序300,500,800存放,则在inode 上的分布区记录上述块列表
- 添加文件名到目录(文件名+inode 映射关系)
查找文件
由inode 号找到数据区对应的内容组合。
通过文件名找不到文件,必须通过inode 才能找到磁盘上的文件。
删除文件
- 直接将inode 对应的inode位图中的1置0即可。
- 将硬链接数-1 ,若硬链接数已经是0则释放磁盘。
3.连接
硬连接:通过inode 引用另一文件,共用一个inode
与文件强关联,本质并不算一个文件,只是原文件的一个引用计数。
直系目录个数=文件引用数-2
软连接:方便快速查询,有独立 inode
是一个独立文件,存储着原文件的路径,相当于Windows下的一个快捷方式。
acm
解释一下文件的三个时间:
- Access 最后访问时间
- Modify 文件内容最后修改时间
- Change 属性最后修改时间