Linux下的管道編程技術(5)

發表于:2013-03-06來源:開源黃頁作者:天狼星點擊數: 標簽:linux
int dup2( int oldfd, int targetfd ) 利用函數dup,我們可以復制一個描述符。傳給該函數一個既有的描述符,它就會返回一個新的描述符,這個新的描述符是傳給它
int dup2( int oldfd, int targetfd )

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

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

  需要注意的是,我們可以在調用fork之前建立一個描述符,這與調用dup建立描述符的效果是一樣的,子進程也同樣會收到一個復制出來的描述符。

  dup2函數跟dup函數相似,但dup2函數允許調用者規定一個有效描述符和目標描述符的id。dup2函數成功返回時,目標描述符(dup2函數的第 二個參數)將變成源描述符(dup2函數的第一個參數)的復制品,換句話說,兩個文件描述符現在都指向同一個文件,并且是函數第一個參數指向的文件。下面 我們用一段代碼加以說明:

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現在也指向它。

  下面我們介紹一個更加深入的示例代碼?;貞浺幌卤疚那懊嬷v的命令行管道,在那里,我們將ls –1命令的標準輸出作為標準輸入連接到wc –l命令。接下來,我們就用一個C程序來加以說明這個過程的實現。代碼如下面的示例代碼3所示。

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

  現在來研究一下管道的接收端。從代碼中可以看出,管道的接收端是由父進程來擔當的。首先關閉stdin描述符(第20行),因為我們不會從機器的鍵盤等 標準設備文件來接收數據的輸入,而是從其它程序的輸出中接收數據。然后,再一次用到dup2函數(第21行),讓stdin變成管道的輸出端,這是通過讓 文件描述符0(即常規的stdin)等于pfds[0]來實現的。關閉管道的stdout端(pfds[1]),因為在這里用不到它。最后,使用 execlp函數把父進程的映像替換為命令wc -1的進程映像,命令wc -1把管道的內容作為它的輸入(第23行)。

示例代碼3:利用C實現命令的流水線操作的代碼
1: #include
2: #include
3: #include
4:
5: int main()

原文轉自:http://yp.oss.org.cn/blog/show_resource.php?resource_id=598

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97