linux系統呼叫dup,dup2,dup3

2021-09-16 18:36:11 字數 2420 閱讀 3602

翻譯自ubuntu下的linux programmer's manual

dup,dup2,dup3-複製乙個檔案描述府。

#include

int dup(int oldfd);

int dup2(int oldfd,int newfd);

#define _gnu_source /*見 feature_test_macros(7) */

#include/* 獲取 o_*的常量定義 */

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

dup()系統呼叫生成檔案描述府oldfd的乙個副本,從未使用的檔案描述符當中選取最小的檔案描述符作為新的檔案描述符。

當成功返回後,舊的檔案描述符和新的檔案描述符可以互換使用,這兩個描述符指向了同乙個開啟的檔案描述(見系統呼叫open()),他們共享同乙個檔案偏移量和檔案狀態標誌。比如說,當使用lseek操作某乙個檔案描述符,改變了該檔案的偏移量的時候,使用另外乙個描述符看到的是相同的偏移量。

這兩個描述符不會共享檔案描述符標誌(例如 close-on-exec標誌)。如果舊的檔案描述符有close-on-exec標誌,則新的檔案描述符沒有。

dup2()

dup2()系統呼叫完成和dup相同的功能。但是dup2並不將未使用的檔案描述符的最小值作為新的檔案描述符,它使用引數newfd作為新的檔案描述符。如果newfd在之前已經開啟了,會先將開啟的檔案關閉,在完成檔案描述符的複製操作。

關閉newfd之前開啟的檔案和複製newfd新的檔案描述符這個操作是原子的。這個操作的原子性至關重要,因為實現close()和dup()兩個函式相同的功能涉及到競爭問題。也就是說在關閉了newfd開啟的檔案之後,將newfd複製為新的檔案描述符之前,newfd有可能已經被重新定義成其他檔案的檔案描述符了。這種情況有可能會發生,比如說主程式被乙個訊號打斷,或者在完成了close操作之後,又有乙個並行執行的執行緒分配了這個檔案描述符。

注意一下要點:

*  如果oldfd不是乙個有效的檔案描述符,此次呼叫失敗,newfd開啟的檔案也不關閉

* 如果oldfd是乙個有效的檔案描述符,並且newfd=oldfd,dup2什麼也不做,直接返回newfd()

dup3()

dup3實現和dup2相同的功能,但有以下差別:

*  呼叫這可以設定close-on-exec標誌,這個操作可以通過指定flags引數裡面的o_cloexec。參考open系統呼叫裡面相同的標誌引數,那裡面解釋了為什麼這樣做是有效的。

* 如果oldfd等於newfd,dup3呼叫失敗,伴隨這乙個錯誤einval。

如果呼叫成功,返回新的檔案描述符。呼叫失敗,返回-1並且errno被設定為適當的值

ebadf :oldfd不是乙個開啟檔案的描述符。

ebadf :newfd超出了檔案描述符的範圍。

ebusy:(只有linux平台下有) 當出現多執行緒資源競爭的時候,dup2或dup3會返回。

eintr: dup2或者dup3被乙個訊號打斷。

einval:dup3的flags引數是乙個無效值

einval:dup3的oldfd等於newfd。

emfile:該程序開啟檔案的檔案描述符的數量達到了上限。

dup3加入了linux 2.6.27版本,從2.9版本開始支援glibc

dup,dup2:posix.1-2001,posix.1-2008,svr4,4.3bsd

dup3是linux特有的

當newfd超過了檔案描述符規定的範圍的時候,dup2()的返回值和funtl(... , f_dupfd, ...)的返回值不同。在某些作業系統上,dup2也會想f_dupfd一樣返回einval。

如果newfd是乙個已經開啟的檔案,執行dup2的時候,在關閉newfd原來開啟的檔案的時候,如果這個時候出錯,那麼這些錯誤就都會被忽略。考慮到這種情況,除非你的程式是單執行緒的,並且在訊號處理程式中不會分配檔案描述符,否則不要在呼叫dup2之前呼叫close,因為多執行緒情況下存在資源競爭(譯者注:如果先呼叫close(newfd)在呼叫dup2(oldfd,newfd)有可能在兩步呼叫操作之間有另外乙個執行緒首先給newfd分配了檔案,從而產生錯誤。)我們可以使用以下的**:

/* 獲取乙個newfd的副本,這樣可以在接下來的過程中檢查close**現的錯誤,ebadf錯誤表示

newfd沒有開啟 */

tmpfd = dup(newfd);

if (tmpfd == -1 && errno != ebadf)

/* 原子操作,複製 */

if (dup2(oldfd, newfd) == -1)

/* 可以通過檢查tmpfd來判斷在關閉newfd的時候是否產生了錯誤 */

if (tmpfd != -1)

}

close(2),fcntl(2),open(2)

linux 系統呼叫

使用者應用可以通過兩種方式使用系統呼叫。第一種方式是通過c庫函式,包括系統呼叫在c庫中的封裝函式和其他普通函式。圖5.2 使用系統呼叫的兩種方式 第二種方式是使用 syscall巨集。2.6.18版本之前的核心,在include asm i386 unistd.h檔案中定義有7個 syscall巨集...

Linux系統呼叫

一 實驗目的和要求 1.學習linux核心的配置和編譯 2.深入理解linux系統呼叫 3.理解arm和x86的cpu模式 系統模式 使用者模式 的不同 4.掌握核心模組的編寫方法。二 實驗器材 1.linux實驗板卡一塊 2.5v 1a電源乙個 3.microusb線一根 4.macos一台 5....

Linux系統呼叫

linux系統呼叫 系統呼叫 system call 是使用者空間訪問核心的唯一手段,除異常和陷入外,他們是核心唯一的合法入口。通常情況下應用程式是通過應用程式設計介面api來訪問函式,而不是直接使用系統呼叫來程式設計。作業系統通常是通過中斷從使用者態切換到核心態。中斷就是乙個硬體或軟體請求,要求c...