1、文件描述符和inode号码是不同的两个东西。


 


2、对于每个进程,系统会建立一个进程控制块(PCB)来保存相关的信息,而这个PCB在内核中的表现其实就是一个称为task_struct的结构体,这个结构体的成员用来保存与此进程有关的相关信息,其中有个成员是struct file_struct  *files,它是用来找到此进程所有打开的文件列表的,files变量指向的是struct file_struct类型的结构体,这个结构体中有一个成员是一个指针数组struct file *fd_array[],这个数组中的每个元素会指向一个struct file的结构体,这个结构体是用来描述一个打开的文件的,有很多的成员,其中有个成员是指向struct file_operation的指针变量,而struct file_operation结构体中包括了很多的函数指针,也就是open,write,realease,read等等对文件进行操作的函数,具体这些函数的实现就是驱动开发需要做的事情。如下图所示。


[转]文件IO详解(二)---文件描述符(fd)和inode号的关系_指针数组


3、在对文件操作前,必须要先打开文件,打开文件过程其实就是让程序能通过某个路径能够找到此文件,关闭文件就是将此路径断开,找不到文件。

13.13 Duplicating Descriptors


You can duplicate a file descriptor, or allocate another file descriptor that refers to the same open file as the original. Duplicate descriptors share one file position and one set of file status flags (see File Status Flags), but each has its own set of file descriptor flags (see Descriptor Flags).

The major use of duplicating a file descriptor is to implement redirection of input or output: that is, to change the file or pipe that a particular file descriptor corresponds to.

You can perform this operation using the ​​fcntl​​ function with the ​​F_DUPFD​​ command, but there are also convenient functions ​​dup​​ and ​​dup2​​ for duplicating descriptors.


The ​​fcntl​​ function and flags are declared in fcntl.h, while prototypes for ​​dup​​ and ​​dup2​​ are in the header file unistd.h.

Function: int dup (int old)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

This function copies descriptor old to the first available descriptor number (the first number not currently open). It is equivalent to ​​fcntl (old, F_DUPFD, 0)​​.

Function: int dup2 (int old, int new)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

This function copies the descriptor old to descriptor number new.

If old is an invalid descriptor, then ​​dup2​​ does nothing; it does not close new. Otherwise, the new duplicate of old replaces any previous meaning of descriptor new, as if new were closed first.

If old and new are different numbers, and old is a valid descriptor number, then ​​dup2​​ is equivalent to:



close (new);
fcntl (old, F_DUPFD, new)


However, ​​dup2​​ does this atomically; there is no instant in the middle of calling ​​dup2​​ at which new is closed and not yet a duplicate of old.

Macro: int F_DUPFD

This macro is used as the command argument to ​​fcntl​​, to copy the file descriptor given as the first argument.

The form of the call in this case is:



fcntl (old, F_DUPFD, next-filedes)


The next-filedes argument is of type ​​int​​ and specifies that the file descriptor returned should be the next available one greater than or equal to this value.

The return value from ​​fcntl​​ with this command is normally the value of the new file descriptor. A return value of -1 indicates an error. The following ​​errno​​ error conditions are defined for this command:

​EBADF​

The old argument is invalid.

​EINVAL​

The next-filedes argument is invalid.

​EMFILE​

There are no more file descriptors available—your program is already using the maximum. In BSD and GNU, the maximum is controlled by a resource limit that can be changed; see Limits on Resources, for more information about the ​​RLIMIT_NOFILE​​ limit.


​ENFILE​​ is not a possible error code for ​​dup2​​ because ​​dup2​​ does not create a new opening of a file; duplicate descriptors do not count toward the limit which ​​ENFILE​​ indicates. ​​EMFILE​​ is possible because it refers to the limit on distinct descriptor numbers in use in one process.


Here is an example showing how to use ​​dup2​​ to do redirection. Typically, redirection of the standard streams (like ​​stdin​​) is done by a shell or shell-like program before calling one of the ​​exec​​ functions (see Executing a File) to execute a new program in a child process. When the new program is executed, it creates and initializes the standard streams to point to the corresponding file descriptors, before its ​​main​​ function is invoked.

So, to redirect standard input to a file, the shell could do something like:



pid = fork ();
if (pid == 0)
{
char *filename;
char *program;
int file;

file = TEMP_FAILURE_RETRY (open (filename, O_RDONLY));
dup2 (file, STDIN_FILENO);
TEMP_FAILURE_RETRY (close (file));
execv (program, NULL);
}


There is also a more detailed example showing how to implement redirection in the context of a pipeline of processes in Launching Jobs.