dup和dup2函式以及管道的實現

2022-03-27 10:56:11 字數 1675 閱讀 2556

疑問:管道應該不是這樣實現的,因為這要求修改程式的**

dup和dup2也是兩個非常有用的呼叫,它們的作用都是用來複製乙個檔案的描述符。它們經常用來重定向程序的stdin、stdout和stderr。這兩個函式的原形如下:

c**  

#include 

int dup( int oldfd );  

int dup2( int oldfd, int targetfd );  

dup()函式

利用函式dup,我們可以複製乙個描述符。傳給該函式乙個既有的描述符,它就會返回乙個新的描述符,這個新的描述符是傳給它的描述符的拷貝。這意味著,這兩個描述符共享同乙個資料結構。例如,如果我們對乙個檔案描述符執行lseek操作,得到的第乙個檔案的位置和第二個是一樣的。下面是用來說明dup函式使用方法的**片段:

c**  

int fd1, fd2;  

...  

fd2 = dup( fd1 );  

需要注意的是,我們可以在呼叫fork之前建立乙個描述符,這與呼叫dup建立描述符的效果是一樣的,子程序也同樣會收到乙個複製出來的描述符。 

dup2()函式

dup2函式跟dup函式相似,但dup2函式允許呼叫者規定乙個有效描述符和目標描述符的id。dup2函式成功返回時,目標描述符(dup2函式的第二個引數)將變成源描述符(dup2函式的第乙個引數)的複製品,換句話說,兩個檔案描述符現在都指向同乙個檔案,並且是函式第乙個引數指向的檔案。下面我們用一段**加以說明:

c**  

int oldfd;  

dup2( oldfd, 1 );  

close( oldfd );  

例子

下面我們介紹乙個更加深入的示例**。回憶一下命令列管道,我們可以將ls –l命令的標準輸出作為標準輸入連線到wc –l命令。接下來,我們就用乙個c程式來加以說明這個過程的實現。**如下所示。 

c**  

#include 

#include 

#include 

int main()  

else   

return 0;  

}  在示例**中,首先在第9行**中建立乙個管道,然後將應用程式分成兩個程序:乙個子程序(第13–16行)和乙個父程序(第20–23行)。接下來,在子程序中首先關閉stdout描述符(第13行),然後提供了ls –l命令功能,不過它不是寫到stdout(第13行),而是寫到我們建立的管道的輸出端,這是通過dup2函式來完成重定向的。在第14行,使用dup2 函式把stdout重定向到管道(pfds[1])。之後,馬上關掉管道的輸入端。然後,使用execlp函式把子程序的映像替換為命令ls –l的程序映像,一旦該命令執行,它的任何輸出都將發給管道的輸入端。 

現在來研究一下管道的接收端。從**中可以看出,管道的接收端是由父程序來擔當的。首先關閉stdin描述符(第20行),因為我們不會從機器的鍵盤等標準裝置檔案來接收資料的輸入,而是從其它程式的輸出中接收資料。然後,再一次用到dup2函式(第21行),讓管道的輸入端作為輸入,這是通過讓檔案描述符0(即常規的stdin)重定向到pfds[0]實現的。關閉管道的stdout端(pfds[1]),因為在這裡用不到它。最後,使用 execlp函式把父程序的映像替換為命令wc -l的程序映像,命令wc -l把管道的內容作為它的輸入(第23行)。

12 dup函式和dup2函式

當呼叫dup函式時,核心在程序中建立乙個新的檔案描述符,該檔案描述符是當前可用檔案描述符的最小數值,這個檔案描述符指向oldfd所擁有的檔案表項。函式原型 include int dup int oldfd 引數說明 oldfd為已經開啟的檔案描述符 返回值 成功返回乙個新檔案描述符,失敗返回 1並...

Linux中dup函式和dup2函式

個人部落格傳送門 linux 中進行檔案描述符的重定向可以使用兩個函式 dup函式和dup2函式,其中還有乙個dup3函式,但是這個是linux後面版本新增的,不是所有的linux核心都支援,在這裡不討論。在linux系統中約定檔案描述符 0 1 2 對應標準輸入 標準輸出 標準錯誤,預設開啟。du...

重定向程式設計 dup和dup2函式

輸入重定向 關閉標準輸入裝置,開啟 或複製 某普通檔案,使其檔案描述符為0.輸出重定向 關閉標準輸出裝置,開啟 或複製 某普通檔案,使其檔案描述符為1.錯誤輸出重定向 關閉標準錯誤輸入裝置,開啟 或複製 某普通檔案,使其檔案描述符為2.1.dup函式 返回值 如成功則返回新的檔案描述符,否則出錯返回...