dup和dup2函數


下面兩個函數都可用來復制一個現存的文件描述符:

#include<unistd.h>
int dup(int filedes);
int dup2(int filedes,int filedes2);
                                                                                                 兩函數的返回值:若成功則返回新的文件描述符,若出錯則返回-1

由dup返回的新文件描述符一定是當前可用文件描述符中的最小值。用dup2則可以用filedes2參數指定新描述符的數值。如果filedes2已經打開,則現將其關閉。如若filedes等於filedes2,則dup2返回filedes2,而不關閉它。

這些函數返回的新文件描述符與參數filedes共享同一文件表項。如圖所示,我們假定執行了:

  newfd=dup(1);  

當此函數開始執行時,假定下一個可用的描述符是3(這是非常可能的,因為0,1和2由shell打開)。因為兩個描述符指向同一文件表項,所以它們共享同一文件狀態標志(讀、寫、添加等)以及同一當前文件偏移量。

每個文件描述符都有它自己的一套文件描述符標志。

 

復制一個描述符的另一種方式是使用fcntl函數,實際上,可調用:

dup(filedes);

等效於

fcntl(filedes,F_DUPFD,0);

而調用

dup2(filedes,filedes2);

等效於

close(filedes2);

fcntl(filedes,F_DUPFD,filedes2);

在后一種情況下,dup2並不完全等效於close加上fcntl。它們之間的區別是:

1)dup2是一個原子操作,而close及fcntl則包括兩個函數調用,有可能在close和fcntl之間插入執行信號捕獲函數,它可能修改文件描述符。

2)dup2和fcntl有某些不同的errno。

 

重點解釋兩個地方:

  • 第3幅圖,要執行dup2(fd, 1);,文件描述符1原本指向tty,現在要指向新的文件somefile,就把原來的關閉了,但是tty這個文件原本有兩個引用計數,還有文件描述符save_fd也指向它,所以只是將引用計數減1,並不真的關閉文件。

  • 第5幅圖,要執行dup2(save_fd, 1);,文件描述符1原本指向somefile,現在要指向新的文件tty,就把原來的關閉了,somefile原本只有一個引用計數,所以這次減到0,是真的關閉了。

1.dup()和dup2()函數格式如下:

#include<unistd.h>
   int dup(int oldfd);
   int dup2(int oldfd, int newfd);

    dup() uses the lowest-numbered unused descriptor for the new descriptor.
    dup2() makes newfd be the copy of oldfd, closing newfd first ifnecessary, but note the following:
   *If oldfd is not a valid file descriptor, then the call fails, and newfd is not closed.
        *If oldfd is a valid file descriptor, and newfd has the same value as oldfd, then dup2() does nothing, and returns newfd.

   1)這兩個函數我們可以用來復制文件描述符。
   2)其中oldfd和newfd分別是復制前文件描述符和復制后的文件描述符。
   3)這兩個函數的調用都將復制文件描述符oldfd,且他們的返回值都為新的文件描述符。
    4)不同點是:dup()的返回值是最小的未用文件描述符;dup2()的返回值是預先制定的文件描述符newfd。
    5)對於dup2(),如果文件描述符newfd正在被使用,則先關閉newfd;如果newfd同oldfd,則不關閉該文件正常返回。
    PS:這是我自己對書上的話進行的分類。


2.首先要弄懂的話,還要對文件描述符了解的清晰:
       關系:進程---(擁有)--->(若干個)文件描述符()---(對應)--->文件
                            |--->文件秒素符(0)
                            |--->文件描述符(1)--->文件(1)
         某進程(n)--|--->文件描述符(2)
                            |--->文件描述符(3)--->文件(3)
                            |.
                            |.
                            |.
                            |--->文件描述符(1023)--->文件(...)
      PS1:由一次open()函數打開的文件是可以有很多個描述符與之相連的;
      PS2:Linux中每個進程可以有1024個文件描述符;
      PS3:文件描述符前三位0、1、2分別對應:
            STDIN_FILENO         0     標准輸入文件
            STDOUT_FILENO     1     標准輸出文件
            STDERR_FILENO     2     標准錯誤輸出文件
  因此就可以較好的開始理解dup(int oldfd)和dup2(int oldfd, int newfd)函數是如何工作的:
      dup()比較好了解:
        系統分配一個新的、未用過的、值為最小的文件描述符指向dup()函數內的參數oldfd所指向的文件,並返回該值。
      dup2()比較難理解:
        1)dup2()先看看oldfd是不是一個有效的文件描述符,如果不是則調用失敗,newfd文件描述符也不關閉;
        2)如果oldfd是一個有效的文件描述符,則檢測newfd是否被使用,如在使用,則將其關閉,並將newfd指向oldfd所指向的文件,並返回newfd;
        3)如果newfd同oldfd,則不關閉該文件正常返回。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM