首页 归档 关于 learn love 工具

linux文件描述符

file descriptor(以下简称fd)又叫文件描述符,他是一个抽象的指示符,用一个整数表示(非负整数)。它指向了由系统内核维护的一个file table中的某个条目(entry)。这个解释可能过于抽象,不过在正式详细介绍fd之前,有必要先了解用户程序和系统内核之间的工作过程。

注: 本文描述的所有场景仅限于类unix系统环境,在windows中这玩意叫file handle(臭名昭著的翻译: 句柄)。

User space & Kernel space

现代操作系统会把内存划分为2个区域,分别为Use space(用户空间) 和 Kernel space(内核空间)。用户的程序在User space执行,系统内核在Kernel space中执行。

用户的程序没有权限直接访问硬件资源,但系统内核可以。比如读写本地文件需要访问磁盘,创建socket需要网卡等。因此用户程序想要读写文件,必须要向内核发起读写请求,这个过程叫system call。

内核收到用户程序system call时,负责访问硬件,并把结果返回给程序。

File Descriptor

上面简单介绍了User space和Kernel space,这对于理解fd有很大的帮助。fd会存在,就是因为用户程序无法直接访问硬件,因此当程序向内核发起system call打开一个文件时,在用户进程中必须有一个东西标识着打开的文件,这个东西就是fd。

file tables

和fd相关的一共有3张表,分别是file descriptor、file table、inode table,如下图所示。

  • file descriptors
    file descriptors table由用户进程所有,每个进程都有一个这样的表,这里记录了进程打开的文件所代表的fd,fd的值映射到file table中的条目(entry)。

另外,每个进程都会预留3个默认的fd: stdin、stdout、stderr;它们的值分别是0、1,2。

  • file table
    file table是全局唯一的表,由系统内核维护。这个表记录了所有进程打开的文件的状态(是否可读、可写等状态),同时它也映射到inode table中的entry。
  • inode table
    inode table同样是全局唯一的,它指向了真正的文件地址(磁盘中的位置),每个entry全局唯一。

流程

当程序向内核发起system call open(),内核将会

  1. 允许程序请求
  2. 创建一个entry插入到file table,并返回file descriptor
  3. 程序把fd插入到fds中。
    当程序再次发起read()system call时,需要把相关的fd传给内核,内核定位到具体的文件(fd –> file table –> inode table)向磁盘发起读取请求,再把读取到的数据返回给程序处理

参考链接

  • https://wiyi.org/linux-file-descriptor.html