正常的文件描述符:
?
在linux下,通過open打開以文件后,會返回一個文件描述符,文件描述符會指向一個文件表,文件表中的節點指針會指向節點表。看下圖:

打開文件的內核數據結構
dup和dup2兩個函數都可以用來復制打開的文件描述符,復制成功后和復制源共享同一個文件表。看下圖:

執行dup后的內核數據結構
?
(1)dup函數
fd1=dup(fd);
fd1和fd共享一個文件表(對fd進行什么操作,fd1也會有相應的操作,fd和fd1是同步的)。
具體解釋:
?
#inclue<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>
int main()
{
char buf[6]={0};
char buf1[6]={0};
int fd = open("file",O_RDWR|O_CREAT,0644);
if(fd < 0)
printf("open error");
printf("fd:%d\n",fd);
//輸出fd=3;
write(fd,"hello,world",12);
lseek(fd,0,SEEK_SET); ?//將文件偏移量置為0,就是從第一個字符開始讀(h開始)
read(fd,buf,5);
printf("fd:%s",buf);//輸出hello
int?fd1 = dup(fd);
read(fd1,buf1,5); //之前做的是對fd的讀寫操作,并沒有對fd1做任何操作。但在這對fd1進行了讀,如果輸出數據。說明fd和fd1是同步的(fd做了什么相當于fd1也做了什么)
printf("fd1:%s\n",buf1); //輸出,worl
//既然輸出的是fd中的內容,說明fd和fd1共用一個文件表,讀到的是,worl,而不是hello(我們在上面將偏移量從第一個字符開始,輸出hello之后,fd的偏移量距離開始有5個字符當我們再次讀fd的時候,它是從第6個字符開始讀的,很明顯,第6個是逗號,往后讀5個,就是,worl),說明偏移量是一致的。(其實不用寫偏移量,因為共用文件表就意味著文件偏移量也共用)
printf("fd1:%d\n",fd1);//輸出fd1 = 4
//fd=3不等于fd1說明不共用同一個文件描述符。這也是dup和dup2的區別。
close(fd);
close(fd1);
return 0;
?
}
(2)dup2函數
?
fd2 = dup2(fd,fd1);
fd2用的fd1(第二個參數)的描述符,用的fd(第一個參數)的文件(和fd共享一個文件表,當然也共享文件偏移量)
強調第幾個參數是因為如果你寫成fd2=dup2(fd1,fd);那么fd2 =fd,和fd1共享同一個文件表。
?
#inclue<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>
int main()
{
int fd = open("file",O_RDWR|O_CREAT,0644);
if(fd < 0)
printf("open error");
printf("fd:%d\n",fd);
//輸出fd=3;
int fd1 =open("text",,O_RDWR|O_CREAT,0644);
if(fd1 < 0)
printf("open error");
printf("fd1:%d\n",fd1);
//輸出fd1=4;
int fd2 = dup2(fd,fd1);
printf("fd2:%d\n",fd2);
//輸出fd2=4;
//fd1 =fd2=4;說明fd2使用了fd1的文件描述符。
?
char buf[12]="hello,world";
write(fd,buf,12); //我們對fd進行了寫,并沒有對fd2進行寫
read(fd2,buf,12);//但是我們對fd2讀的時候,如果沒有寫,怎么可能讀出來呢
printf("fd2:%s\n",buf);//事實是讀出來了
//輸出fd2:hello,world ? ?//說明fd和fd2共用一個文件表。
?
lseek(fd,5,SEEK_SET);//距離開始偏移5位,說明下次讀的時候是從第6個開始,注意我們是對fd進行偏移,沒有對fd2偏移
read(fd2,buf,5); ?//但是如果讀fd2結果是從第6個字符開始的
buf[5]=0; //如果不寫這句,輸出的buf是按照12個字符輸出的。因為定義buf的時候數組中可以放12個字符。
printf("fd2:%s\n",buf);//輸出fd2:,worl ?//說明fd2和fd共享文件偏移量。
close(fd);
close(fd2);
return 0;
}
dup和dup2的區別
dup:fd1= dup(fd);目標描述符使用了fd的文件表
dup2:fd2 = dup2(fd1,fd)目標描述符使用了fd1的描述符,使用了fd的文件表