Unix 網絡編程 dup和dup2函數

dup和dup2也是兩個很實用的調用,它們的做用都是用來複制一個文件的描寫敘述符。數據結構

它們經常常使用來重定向進程的stdin、stdout和stderr。這兩個函數的原形例如如下:app

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

dup()函數:

利用函數dup。咱們可以複製一個描寫敘述符。

傳給該函數一個既有的描寫敘述符,它就會返回一個新的描寫敘述符,這個新的描寫敘述符是傳給它的描寫敘述符的拷貝。這意味着,這兩個描寫敘述符共享同一個數據結構。好比,假設咱們對一個文件描寫敘述符運行lseek操做,獲得的第一個文件的位置和第二個是同樣的。如下是用來講明dup函數用法的代碼片斷:
函數

int fd1, fd2;
...
fd2 = dup( fd1 );

需要注意的是,咱們可以在調用fork以前創建一個描寫敘述符。這與調用dup創建描寫敘述符的效果是同樣的。子進程也相同會收到一個複製出來的描寫敘述符。



dup2()函數:

dup2函數跟dup函數類似,但dup2函數贊成調用者規定一個有效描寫敘述符和目標描寫敘述符的id。dup2函數成功返回時,目標描寫敘述符(dup2函數的第二個參數)將變成源描寫敘述符(dup2函數的第一個參數)的複製品,換句話說,兩個文件描寫敘述符現在都指向同一個文件,並且是函數第一個參數指向的文件。如下咱們用一段代碼加以說明:
spa

 int oldfd;
 oldfd = open("app_log", (O_RDWR | O_CREATE), 0644 );
 dup2( oldfd, 1 );
 close( oldfd );

在本例中,咱們打開了一個新文件,稱爲「app_log」,並收到一個文件描寫敘述符,該描寫敘述符叫作fd1。咱們調用dup2函數。參數爲oldfd和1,這會致使用咱們新打開的文件描寫敘述符替換掉由1表明的文件描寫敘述符(即stdout,因爲標準輸出文件的id爲1)。不論什麼寫到stdout的東西,現在都將改成寫入名爲「app_log」的文件裏。需要注意的是,dup2函數在複製了oldfd以後,會立刻將其關閉,但不會關掉新近打開的文件描寫敘述符,因爲文件描寫敘述符1現在也指向它。



如下咱們介紹一個更加深刻的演示樣例代碼。回顧一下命令行管道,咱們可以將ls –l命令的標準輸出做爲標準輸入鏈接到wc –l命令。接下來。咱們就用一個C程序來加以說明這個過程的實現。代碼例如如下所看到的。命令行


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
    int pfds[2];

    if ( fork() == 0 ) {

        close(1);
        dup2( pfds[1], 1 );
        close( pfds[0] );
        execlp( "ls", "ls", "-l", NULL );

    } else {

        close(0);
        dup2( pfds[0], 0 );
        close( pfds[1] );
        execlp( "wc", "wc", "-l", NULL );

    }

    return 0;
}

在演示樣例代碼中,首先創建一個管道,而後將應用程序分紅兩個進程:一個子進程和一個父進程。接下來,在子進程中首先關閉stdout描寫敘述符(第13行)。而後提供了ls –l命令功能。只是它不是寫到stdout,而是寫到咱們創建的管道的輸出端。這是經過dup2函數來完畢重定向的。使用dup2 函數把stdout重定向到管道(pfds[1])。

以後,當即關掉管道的輸入端。而後,使用execlp函數把子進程的映像替換爲命令ls –l的進程映像,一旦該命令運行,它的不論什麼輸出都將發給管道的輸入端。

現在來研究一下管道的接收端。從代碼中可以看出,管道的接收端是由父進程來擔當的。首先關閉stdin描寫敘述符,因爲咱們不會從機器的鍵盤等標準設備文件來接收數據的輸入,而是從其餘程序的輸出中接收數據。code

而後,再一次用到dup2函數。讓管道的輸入端做爲輸入,這是經過讓文件描寫敘述符0(即常規的stdin)重定向到pfds[0]實現的。關閉管道的stdout端(pfds[1]),因爲在這裏用不到它。最後,使用 execlp函數把父進程的映像替換爲命令wc -l的進程映像,命令wc -l把管道的內容做爲它的輸入。blog

相關文章
相關標籤/搜索