C语言-文件描述符/文件偏移量/文件指针

在 Linux C 语言中,经常会碰到文件描述符、文件偏移量,和文件指针,这篇文章就来介绍这三个概念。

文件描述符

文件描述符是在 Linux 下的一种概念,用于标识特定能够进程正在访问的一个文件。当打开一个文件或创建一个文件,之后操作系统在内核级别为该文件分配的唯一标识符。它可以用来标识其对应的特定文件。通常来说文件描述符是一个小的非负整数。
在 Linux 中每个进程最多可以拥有 1024 个文件描述符,并且有自己的文件描述符表,其中三项对于进程是固定的,并且是由系统自动打开的:

  • 文件描述符 0: 标准输入文件 对于一般进程来说是键盘
  • 文件描述符 1: 标准输出文件 一般是输出到显示器
  • 文件描述符 2: 标准错误输出文件 一般也是输出到显示器

其在 <fcntl.h> 的定义如下:

1
2
3
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2

之后操作系统从 3 开始依次给进程需要的文件分配文件描述符。
因为文件系统是以内核级别进行打开文件,所以其存在于内核空间,是进程级别的资源。如果要分配新的文件描述符,需要使用系统调用函数来进行。比如使用 open()
当进程请求打开一个文件时,操作系统为进行一系列操作(权限检查、创建内核数据结构等),如果成功就会返回分配的文件描述符给进程。在之后操作系统要对该文件操作时,只需要告诉内核该文件的文件描述符而不需要每次都告诉操作系统冗长的路径。

文件偏移量

在 Linux 中每一个打开的文件都有一个与之相关联的文件偏移量,通常为非负整数。用以度量从文件开始处计算的字节数。读写操作都从当前偏移量开始,并使偏移量增加所读写的字节数。
而当两个进程同时打开一个文件时,因为每个进程都有自己的文件描述符表,所以每个进程都会有自己对当前文件的文件偏移量。
可以通过 lseek() 来修改文件偏移量从而实现随机访问文件即可以跳转到任意位置。
lseek 可以将文件设置的文件偏移量超过文件结束符,当瑕疵调用 write() 函数时可以将文件的长度延伸到所需的长度,并用无意义的字符填充这快空间。

文件指针

每次调用相应的函数处理文件时都会调用内核的系统调用,每次通过内核对文件进行操作效率太低,因而有了使用文件指针结构体的流操作。
文件指针是 c 语言标准库(stdio.h)中定义的一个结构体指针 FILE*。可以看作是标准库对文件描述符和文件偏移量以及它的信息的一层封装和抽象。
文件指针存在于用户空间带有缓冲区,在用户层建立了流缓冲区。它先将数据写入流缓冲区,然后再一次性进入内核缓冲区使用系统调用写入文件,减少了系统调用次数,提升了效率。
而且文件指针是跨平台的,只要是有 c 库的操作系统都是可以使用文件指针的!

萌ICP备20241614号