文件描述符和文件句柄(和 C)

Mar*_*ron 5 c linux io file

有人能准确地向我解释文件描述符和文件句柄之间的区别吗(与 Windows 对该术语的定义分开;我对它们的定义很好奇,但这需要更长的答案)?

从我从维基百科收集的信息来看,文件描述符是文件描述符表中的一个索引,它指向文件表中的文件名,而文件名又指向 inode 表中的一个 inode。文件句柄是一种存储文件描述符的数据结构。

  • 文件描述符是否只是文件描述符表中的一个索引(即,索引值就是文件描述符)?
  • 或者由其索引标识的文件描述符表元素是否存储文件描述符(假设索引是一个数字,使它们可能是两个不同的数字)?
  • “文件句柄”只是 C 中存储文件描述符的 FILE 数据结构的一个术语吗?或者文件句柄是否引用了一些其他数据结构,它存储了一个文件描述符,与 C 数据结构 (FILE) 分开?关于文件句柄数据结构的性质,谁能告诉我什么?

fgh*_*ghj 8

首先,我们需要单独的接口和实现。在符合 POSIX 的系统上,您将得到int结果open(2),然后您可以使用它int进行写入、读取等操作。这是界面。

在内核中,为具体的进程管理打开的文件,映射到int 内核用来管理文件的某种结构,可以有多种实现方式,可以是数组,可以是二叉树等等。

对于 Linux 内核,对于每个打开的文件,它都有struct file,并且要使用int内核必须映射int到struct file. 它以如此简单的方式做到这一点 - fdt->fd[fd],其中ftd是指向 的指针struct fdtable,fd是文件描述符(int)(我不描述内核如何处理多线程访问表的方式)。这是 Linux 内核中的当前实现。将来可以改变。

返回的文件句柄CreateFile以类似于文件描述符的方式使用,它是整数,用作索引来访问struct file每个进程表中的 Windows 模拟。

所以我认为文件句柄和文件描述符可以用作同义词,但通常当谈论file handle意味着 HANDLE 时,当谈论文件描述符时谈论 POSIX intreturn by open. 在windows上 也用于管理事件、GUI窗口等,这在POSIX系统上HANDLE并非如此,但在POSIX系统上也用于管理套接字,而在windows上这是不可能的,直到winsock 2。file descriptorsfile descriptors

还有关于文件。上面接口中的 FILE 和file descriptor,file handle里面有其中一个,加上一些数据来管理缓冲 I/O。例如来自流行的 linux C 运行时 glibc:

struct _IO_FILE {
  int _flags;           /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags

  /* The following pointers correspond to the C++ streambuf protocol. */
  /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
  char* _IO_read_ptr;   /* Current read pointer */
  char* _IO_read_end;   /* End of get area. */
  char* _IO_read_base;  /* Start of putback+get area. */
  char* _IO_write_base; /* Start of put area. */
  char* _IO_write_ptr;  /* Current put pointer. */
  char* _IO_write_end;  /* End of put area. */
  char* _IO_buf_base;   /* Start of reserve area. */
  char* _IO_buf_end;    /* End of reserve area. */
  /* The following fields are used to support backing up and undo. */
  char *_IO_save_base; /* Pointer to start of non-current get area. */
  char *_IO_backup_base;  /* Pointer to first valid character of backup area */
  char *_IO_save_end; /* Pointer to end of non-current get area. */

  struct _IO_marker *_markers;

  struct _IO_FILE *_chain;

  int _fileno;
//...
};
Run Code Online (Sandbox Code Playgroud)

正如你所看到的_fileno,它是file descriptor通过调用glibc从操作系统获取的open(2)。但它有很多东西可以缓冲、翻译行尾等。