一个文件描述符实际上存储了多少信息?

7
这或许是一个奇怪的问题,但是当我打开一个文件时:
int fd;
fd = open("/dev/somedevice", O_RDWR);

我到底得到了什么?我可以看到man页面上说:
open()函数将返回一个文件描述符,该文件描述符是该进程当前未打开的最低文件描述符

但是就这样吗?它只是一个int还是背后附带有数据?我之所以问是因为我发现了一些代码(Linux/C),我们正在从用户空间打开文件:

//User space code:
int fdC;

if ((fdC = open(DEVICE, O_RDWR)) < 0) {
    printf("Error opening device %s (%s)\n", DEVICE, strerror(errno));
    goto error_exit;
}
while (!fQuit) {
    if ((nRet = read(fdC, &rx_message, 1)) > 0) {

在内核端,为该模块(提供fd)提供文件操作的函数将读取映射到n_read()函数:

struct file_operations can_fops = { 
    owner:      THIS_MODULE,
    lseek:  NULL, 
    read:   n_read,

接下来,文件描述符在n_read()中被使用,但是它被访问以获取数据:

int n_read(struct file *file, char *buffer, size_t count, loff_t *loff)
{
    data_t * dev;

    dev = (data_t*)file->private_data;

所以...我猜这里发生的一件事情要么是:

A) 从open()返回的文件描述符包含的数据不仅仅是一个描述性整数值
或者
B) 在用户空间中调用"read"的映射并不像我想象的那么简单,这个方程中缺少一些代码。

是否有任何可以帮助指导我的输入?


1
fQuit在哪里声明的?是的,文件描述符只是整数。关于它们的任何信息都必须通过从内核文件描述符表中进行系统调用来获取。 - Sergey L.
@user1700513 - 你可以假设 fQuite 的值为0。 - Mike
3个回答

10

文件描述符只是一个 int 值。内核使用它作为索引来访问包含所有相关信息的表,包括文件位置,文件操作(内核提供的read()write()mmap()等系统调用)等。

当你 open() 一个文件或设备时,内核会为你的进程创建一个新的文件描述符条目,并填充内部数据,包括文件操作。

当使用有效的文件描述符进行 read()write()mmap() 等操作时,内核简单地查找文件描述符表中对应的文件操作,并调用相应的内核函数。如此简单直接。


谢谢,非常简洁明了的解释... 我想我只是在试图把这个问题弄得过于复杂了。 :) - Mike

3

除了@Nominal Aminal的好答案之外,它是一个整数,但它指向内核中称为文件描述符表的结构体入口。这至少适用于Linux。该结构体的几个字段中,一个有趣的字段是:

FILE * pointer; // descriptor to / from reference counts etc.

您可能对以下API感兴趣,它们可以在给定FILE *或描述符的情况下返回另一个:

如何从文件描述符获取FILE *并进行反向转换


文件描述符表,系统打开文件表:http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.genprogc/doc/genprogc/fdescript.htm - n611x007
开放文件的内核数据结构:http://www.cim.mcgill.ca/~franco/OpSys-304-427/lecture-notes/node27.html - n611x007
这是完全不正确的。在Linux中,标准I/O(以及fileno()fdopen())使用的FILE *与内核struct file没有任何关系,除了名称上可能有些相似之外。 - Nominal Animal

1
我认为这只是一个 int
来自维基百科的内容:

通常,文件描述符是内核驻留数据结构中条目的索引,该数据结构包含所有打开文件的详细信息。在 POSIX 中,此数据结构称为文件描述符表,每个进程都有自己的文件描述符表。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接