文件描述符
定义
- 一个非负整数
- 应用程序利用文件描述符来访问文件
- file descriptor,简写为fd
系统调用
- 打开现存文件或新建文件时,内核会返回一个文件描述符
读写文件也需要使用文件描述符来指定待读写的文件
打开文件
int open(char *path, int flags, mode_t mode);
内核会返回一个文件描述符fd用来表示该文件
读写时需要使用fd指定待读写的文件
读写文件
int read(int fd, void *buf, size_t size);
int write(int fd, void *buf, size_t size);
- fd是open返回的文件描述符
- 用于指定待读写的文件
例子:访问文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd;
fd = open("/etc/hosts", O_RDONLY);
char buf[1024];
int count;
count = read(fd, buf, sizeof(buf));
buf[count] = 0;
puts(buf);
close(fd);
return 0;
}
output:
$ ./a.out
127.0.0.1 localhost
$ _
内核实现
简介
内核实现文件描述符的的数据结构
- 索引节点
- file结构体
- 文件描述符表
- 进程控制块
索引节点
索引节点(inode)是unix文件系统中的一种数据结构
索引节点保存了文件的元信息数据
- 文件的大小
- 文件存放在磁盘的位置
- 文件的创建时间、修改时间
- 文件的所有者
- 文件的访问权限
file结构体
内核使用file结构体表示一个被打开的文件
file结构体存了被打开文件的信息
- 文件对应的索引节点(inode)
- 文件的当前访问位置
- 文件的打开模式
- 只读、只写、可读可写
文件描述符表
- 文件描述符表是一个数组
- 数组的元素类型是指针,指针指向一个file结构体
- 用于保存被打开的文件
- 内核打开文件时,分配一个file结构体表示被打开的文件,将该file结构体指针保存在文件描述符表中
打开文件的过程
- 找到文件对应的索引节点inode
- 分配一个file结构体
file结构体的inode字段指向第1步的inode
file结构体的文件访问位置字段初始化为0 - 从文件描述符表中找一个空闲项
指向第2步的file结构体
返回该空闲项在数组中的的下标,即fd
进程控制块
- 进程控制块是操作系统表示进程状态的数据结构
- 存放用于描述进程情况及控制进程运行所需的全部信息
- 进程标识信息
- 处理机状态
- 进程调度信息
- 打开文件列表,即文件描述符表,记录了该进程打开的文件
私有的文件描述符表
文件描述符表对进程来说是私有的
- 每个进程都有一个私有的文件描述符表
- 操作系统有N个进程,则对应有N张文件描述符表
两个进程打开不同的文件,文件描述符可能是相同的 - 进程A打开文件a.txt,open返回值是3
- 进程B打开文件b.txt,open返回值也可能是3
标准输入输出
简介
每个进程执行时,会自动打开三个标准文件
- 标准输入文件,通常对应终端的键盘
- 标准输出文件,通常对应终端的屏幕
- 标准错误输出文件,通常对应终端的屏幕
进程的文件描述符表前三项已经被打开了 - 第0项,对应标准输入
- 第1项,对应标准输出
- 第2项,对应标准错误输出
例子
#include <unistd.h>
int main()
{
char buf[80];
int count;
count = read(0, buf, sizeof(buf));
buf[count] = 0;
write(1, buf, count);
}
output:
$ ./a.out
hello
hello
$ _