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節點指標
也就是說,我們圖一中管道的兩端,可以進行替換來看看如下圖,管道資料傳遞實際就是兩個節點之間資料的傳遞,而呼叫dup2函式時,其步驟為:1.關閉第二個引數的標誌; 2.將檔案指標指向第一個引數的檔案表
請注意:管道是利用核心緩衝區、環形佇列實現的,是偽檔案。a[0]、a[1]指標是核心緩衝區裡的某個地方,由於父子關係,兩個程序共用這一塊記憶體。
三、輸出重定向
原理講解差不多了,那麼我們將剛才講解的運用一下,如何將螢幕輸出 重定向到一個檔案呢?實際就是STDOUT_FILENO與某個檔案描述符的dup2函式操作。
dup2(fd1, STDOUT_FILENO);
這樣就達到先關閉STDOUT_FILENO的標誌,再將其指標指向fd1的檔案表,接著printf出來的資料都將被放入fd1所指向的空間,也就達到了重定向的目的。