简体   繁体   English

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

[英]File Descriptors and File Handles (and C)

Can someone explain to me precisely the difference between a file descriptor and a file handle (separate from Windows' definition for the term; I'm curious about their definition, but that would require a much longer answer)? 有人可以准确地向我解释文件描述符和文件句柄之间的区别吗(与Windows的术语定义不同;我很好奇它们的定义,但这需要更长的答案)?

From what I have gathered from Wikipedia, a file descriptor is an index in a file descriptor table, which points to a file name in a file table, which in turn points to an inode in an inode table. 根据我从Wikipedia收集的信息,文件描述符是文件描述符表中的索引,它指向文件表中的文件名,而文件名又指向inode表中的inode。 File handle is a type of data structure that stores a file descriptor. 文件句柄是一种存储文件描述符的数据结构。

  • Is a file descriptor simply an index in the file descriptor table (ie, the index value simply is the file descriptor)? 文件描述符是否只是文件描述符表中的索引(即,索引值仅仅是文件描述符)?
  • Or does the file descriptor table element, identified by its index, store the file descriptor (making them likely two different numbers, assuming the index is a number)? 还是由文件索引表元素(由其索引标识)存储文件描述符(假设索引为数字,使其可能为两个不同的数字)?
  • Is "file handle" simply a term for the FILE data structure in C which stores file descriptors? “文件句柄”是否只是C中存储文件描述符的FILE数据结构的术语? Or does file handle refer to some other data structure, which stores a file descriptor, separate from the C data structure (FILE)? 还是文件句柄引用了其他一些与C数据结构(FILE)分开存储文件描述符的数据结构? What else can anyone tell me about the nature of file handle data structures? 关于文件句柄数据结构的本质,还有谁能告诉我?

First of all we need separate interface and implementation. 首先,我们需要单独的接口和实现。 On POSIX conforming systems, you get int as result of open(2) and after that you can use this int for writing, reading and so on operations. 在符合POSIX的系统上,您可以通过open(2)获得int ,然后可以使用该int进行写入,读取等操作。 This is interface. 这是界面。

In the kernel, which manage open files for concrete process, map from int to some structure that kernel used to manage files may be implemented in many ways, may be array, may be binary tree and so on. 在内核中,它管理用于具体过程的打开文件,从int映射到内核用于管理文件的某些结构,可以以多种方式实现,可以是数组,可以是二叉树等等。

As for linux kernel, for each open file it has struct file , and to work with int kernel has to map int to address of struct file . 对于linux内核,对于每个打开的文件,它都有struct file ,要使用int内核,必须将int映射到struct file地址。 It do it in such simple way - fdt->fd[fd] , where ftd is pointer to struct fdtable , fd is file descriptor ( int ) (I do not describe the way of how kernel handle multi thread access to tables). 它以这种简单的方式执行fdt->fd[fd] ,其中ftd是指向struct fdtable指针, fd是文件描述符( int )(我没有描述内核如何处理对表的多线程访问的方式)。 This is current implementation in Linux kernel. 这是Linux内核中的当前实现。 It can be changed in the future. 将来可以更改。

File handle that return CreateFile is used in similar to file descriptor way, it is integer, that used as index to access Windows analog of struct file in per process table. 返回CreateFile文件句柄以类似于文件描述符的方式使用,它是整数,用作在每个进程表中访问struct file Windows模拟的索引。

So I think that file handle and file descriptor may be used as synonyms, but usually when talk about file handle mean HANDLE, and when talk about file descriptors talk about POSIX int return by open . 因此,我认为可以将文件句柄和文件描述符用作同义词,但是通常在谈论file handle意味着HANDLE时,以及在谈论文件描述符时谈论POSIX int return by open On windows HANDLE also used to manage events, GUI windows and so on, this is not true for file descriptors on POSIX systems, but on POSIX systems file descriptors also used to manage sockets, while on windows this was impossible until winsock 2. 在窗户HANDLE还可以用来管理事件,GUI窗口等等,这不是真正的file descriptors的POSIX系统,但在POSIX系统file descriptors还可以用来管理插座,而在Windows上这是不可能的,直到Winsock 2的。

And about FILE. 关于文件。 FILE in interface above file descriptor and file handle , it has one of them inside, plus some data to manage buffered I/O. file descriptorfile handle上方的接口中的FILE,它内部有其中之一,外加一些数据来管理缓冲的I / O。 For example from popular linux C runtime glibc: 例如,来自流行的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;
//...
};

As you can see it has _fileno , it file descriptor which glibc get from OS by open(2) call. 如您所见,它具有_fileno ,它是glibc通过open(2)调用从操作系统获取的file descriptor But it has a lot of stuff to buffering, translate end of lines etc. 但是它有很多东西要缓冲,转换行尾等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM