1. 程式人生 > >dup2函式引數順序配圖分析

dup2函式引數順序配圖分析

引言: 之前在學習Linux程序間通訊時,使用了管道來傳遞資料。而管道與管道之間對接採用dup2函式進行連線,發現dup2函式的兩個引數填充順序著實有趣,兩個管道之間到底是怎麼對接成功的呢?學習了一下以配圖分析的方式呈現。

一、使用場合

首先介紹這個圖: 父程序fork出一個子程序,傳遞資料給程序,希望子程序去呼叫一個外部程式來處理並返回資料(比如CGI程式)。
流程: 父程序fork出子程序 ——> 父程序向a[1]寫入資料 ——> 父程序等待 ——> 子程序呼叫外部程式 ——> 外部程式通過STDIN_FILENO拿資料(比如getchar()) ——> 外部程式執行 ——> 外部程式通過STDOUT輸出結果(比如printf()) ——> 父程序通過b[0]拿資料
這裡寫圖片描述

可以發現,圖中(1)、(2) dup2函式的引數順序,都是讀寫管道對接,到底為什麼要這麼寫呢,這個順序是固定的嗎?需要背嗎?其實很多時候我們按照這個順序寫,卻沒有考慮為什麼這麼寫,那麼接下來我們來闡述對接的原理。

二、瞭解檔案描述符

上圖中的 STDIN_FILENO、STDOUT_FILENO, a[0]、a[1]、b[0]、b[1] 都是int型的檔案描述符。所以首先我們得知道檔案描述符是個什麼東西,這樣才能夠解釋管道對接的原理

下面這張圖來自百度百科,可以看到,檔案描述符是是一個程序表項中的檔案描述符表中的一項,它由fd標誌和檔案指標構成。fd標誌:在exec後,根據標誌為來決定該檔案描述符能不能跨exec開啟。檔案指標:指向一個檔案表,該檔案表包含了該程序對檔案的操作狀態、偏移量以及V節點指標

。 然而V節點唯一,檔案表可以多個(多個程序開啟同一個檔案的情況)。最後時i索引節點,i索引節點中包含了檔案的所有者,檔案長度,指向檔案實際資料塊在磁碟上位置的指標等。
這裡寫圖片描述

也就是說,我們圖一中管道的兩端,可以進行替換來看看如下圖,管道資料傳遞實際就是兩個節點之間資料的傳遞,而呼叫dup2函式時,其步驟為:1.關閉第二個引數的標誌; 2.將檔案指標指向第一個引數的檔案表
請注意:管道是利用核心緩衝區、環形佇列實現的,是偽檔案。a[0]、a[1]指標是核心緩衝區裡的某個地方,由於父子關係,兩個程序共用這一塊記憶體。
這裡寫圖片描述

三、輸出重定向

原理講解差不多了,那麼我們將剛才講解的運用一下,如何將螢幕輸出 重定向到一個檔案呢?實際就是STDOUT_FILENO與某個檔案描述符的dup2函式操作。

dup2(fd1, STDOUT_FILENO);

這樣就達到先關閉STDOUT_FILENO的標誌,再將其指標指向fd1的檔案表,接著printf出來的資料都將被放入fd1所指向的空間,也就達到了重定向的目的。