铭记一句大师的话,“每个open调用都会在文件描述符表和文件表中分配一个唯一表项,但在内存索引节点表(V节点表)中,每个文件只对应一个表项”
说的“每个open调用都会在文件表中分配一个唯一表项”,说明,它们拥有不同的偏移。
举一个例子:
进程A
fp1 = fopen ("a.data","r");
fp2 = fopen ("a.data","r");
fread ( buf1,1,10,fp1 );
fread ( buf2,1,20,fp2 );
off1 = ftell(fp1); // off1 = 10
off2 = ftell(fp2); // off2 = 20
fd1 = fileno(fp1);
fd2 = fileno(fp2);
其中fd1 和 fd2 指向的是不同的文件表项。
所以说,连续open多次,并不会使文件表项结构中的引用计数加1。那么什么时候文件表项中的引用数会加1呢?有两种情况,一个是dup 另一个是fork
fork跟上面的情况差不多,完全把文件描述符表给复制了一份,然后在相应的文件表项中的引用计数加了1.
设计这种结构的大师Thompson说过,“把文件表作为一个独立的数据结构来实现,是为了在若干用户文件描述符之间能够共享偏移量指针”。就DUP而言,同一进程的不同描述符共享同一文件的偏移指针;就FORK而言,不同进程的同一描述符共享同一文件偏移指针(这涉及到进程切换,数据就可能出现混乱,为了保证数据的一致性进程锁就出现了)。