1. 程式人生 > >linux dup,dup2,dup3 複製一個檔案描述符

linux dup,dup2,dup3 複製一個檔案描述符

dup,dup2,dup3  --duplicate a file descriptor複製一個檔案描述符

大綱

  #include <unistd.h>

  int dup(int oldfd);

  int dup2(int oldfd , int newfd);

  int dup3(int oldfd , int newfd , int flags);

描述:

這些系統呼叫 建立了一個原始檔案描述符的複本.

dup()   為新複製的檔案描述符使用一個未用的最小數字

dup2()  複製原先的檔案描述符 到一個新的檔案描述符上.如果有必要將關閉新的描述符所對映的開啟檔案.但是請注意下面: 

                      ①如果舊的檔案描述符不是一個有效的檔案描述符,系統呼叫失敗,新的檔案描述符不會關閉.

                      ②如果舊的檔案描述符是一個有效的檔案描述符,但是新的檔案描述符和舊的檔案描述符相同,dup2()不做任何事情

      成功執行這些系統呼叫之後,新的檔案描述符和舊的檔案描述符就可以進行交換使用了.他們代表著相同的檔案描述符,指向相同的開啟檔案,因此,他們共享該開啟檔案的

檔案偏移量 和 檔案狀態標誌.舉個例子,如果檔案偏移量被其中一個檔案描述符使用lseek()修改了,那麼另外一個檔案描述符的檔案偏移量也隨之修改.

但是請注意:他們不共享(the close-on-exec flag)標誌位.  close-on-exec標誌位在複製檔案描述符時是關閉的.

(close-on-exec標誌位的作用是:它屬於該檔案描述符的一個屬性,表示子程式是否能夠繼承該檔案描述符,如果標誌位off,表示未設定,則子程序可以使用該檔案描述符,on表示已設定,那麼就不可使用.這裡根據意思也很好理解.詢問你是否在exec呼叫時close檔案描述符,如果off,則可用,on則不可用--譯者注).

       dup3()  其實和dup2()相同,除了以下兩點:

                     ①.它能夠設定close-on-exec 標誌位的開啟和關閉.它通過在flag引數位設定 O_CLOEXEC 來強行設定 close-on-exec 標誌位的開啟.這樣子程序就不能夠使用該檔案描述符了.檢視關於close-on-exec標誌位的更多資訊,請參看open(2),瞭解為什麼該標誌位是有用的.

                     ②如果舊的檔案描述符和新的檔案描述符相同,dup3()呼叫失敗,返回EINVAL 錯誤.

返回值:

     成功呼叫之後,這些系統呼叫返回一個新的檔案描述符, 如果錯誤,返回 -1,並且errno 錯誤型別將被合理的設定.

錯誤:

       EBADF:舊的檔案描述符不是一個開啟的檔案描述符或者新的檔案描述符超出了檔案描述符允許的範圍時返回

       EBUSY:(Linux only)當呼叫dup2()或者dup3()的時候, 系統正在執行open()或者 dup()時返回.

       EINTR:dup2()或者 dup3()系統呼叫被訊號打斷時返回.

       EINVAL: dup3() 標誌位包含一個無效值,或者舊的檔案描述符和新的檔案描述符相同時返回.

       EMFILE:當程序已經開啟最大的檔案描述符數字之後,嘗試複製檔案描述符時,無檔案描述符數字可用時返回.

版本:  

     dup3()是在版本linux2.6.27增加的,glibc是從版本2.9增加的.

注意點:

    dup2()在新的檔案描述符超出檔案描述符允許的範圍時返回的錯誤是不同於fcntl(...,F_DUPFD,...).在一些系統上,dup2()返回的EINVAL和 F_DUPFD相同.

    如果新的檔案描述符是開啟的,任何將在close()呼叫時報告的錯誤會丟失. 一個小心的程式設計師將會在呼叫 dup2()或者dup3()之前,關閉 新的檔案描述符.