簡體   English   中英

實際例子使用dup或dup2

[英]practical examples use dup or dup2

我知道dup / dup2做了什么,但我不知道它什么時候會被使用。

任何實際的例子?

謝謝。

一個示例用途是I / O重定向。 為此你分叉一個子進程並關閉stdin或stdout文件描述符(0和1)然后你在你選擇的另一個filedescriptor上做一個dup(),它現在將被映射到最低的可用文件描述符,這是在這里案例0或1。

使用它,您現在可以執行任何可能不知道您的應用程序的子進程,並且只要子進程在stdout上寫入(或從stdin讀取,無論您配置什么),數據都會寫在提供的文件描述符上。

Shell使用它來實現帶管道的命令,例如/bin/ls | more /bin/ls | more通過將一個進程的stdout連接到另一個進程的stdin。

理解dup和dup2的最佳方案是重定向。
首先我們需要知道的是系統有3個默認文件id(或指示輸出或輸入源的變量)來處理輸入和輸出。 他們是stdinstdoutstderr ,在整數他們是012 大多數函數如fprintfcout都直接輸出到stdout
如果我們想重定向輸出,一種方法是給出,例如, fprintf函數更多的參數指示inout
但是,有一種更優雅的方式:我們可以覆蓋默認文件ID,使它們指向我們想要接收輸出的文件。 dupdup2在這種情況下完全正常工作。
現在讓我們從一個簡單的例子開始:假設我們想將fprintf的輸出重定向到名為“chinaisbetter.txt”的txt文件。 首先,我們需要打開這個文件

int fw=open("chinaisbetter.txt", O_APPEND|O_WRONLY);

然后我們希望stdout使用dup函數指向“chinaisbetter.txt”:

dup2(fw,1);

現在stdout(1)指向“chinaisbetter.txt”的描述符,即使它仍然是1,但輸出現在被重定向。
然后您可以正常使用printf ,但結果將在txt文件中,而不是直接顯示在屏幕上:

printf("Are you kidding me? \n");

PS

  1. 這只是一個直觀的解釋,您可能需要檢查手冊頁或詳細信息。 實際上,我們在這里說“復制”,他們並沒有復制一切。

  2. 這里的文件ID是指文件的處理程序。 上面提到的文件描述符是記錄文件信息的結構。

當您對POSIX函數感到好奇時,特別是那些似乎自己復制的函數,通常檢查標准本身是件好事。 在底部,您通常會看到示例,以及兩者的實現(和存在)背后的推理。

在這種情況下:

以下部分內容豐富。

例子

將標准輸出重定向到文件

以下示例關閉當前進程的標准輸出,重新分配標准輸出以轉到pfd引用的文件,並關閉原始文件描述符以進行清理。

#include <unistd.h>
...
int pfd;
...
close(1);
dup(pfd);
close(pfd);
...

重定向錯誤消息

以下示例將消息從stderr重定向到stdout

#include <unistd.h>
...
dup2(2, 1); // 2-stderr; 1-stdout
...

應用用法

沒有。

合理

dup()dup2()函數是多余的。 他們的服務也由fcntl()函數提供。 它們已被包含在IEEE Std 1003.1-2001的這一卷中,主要是出於歷史原因,因為許多現有的應用程序使用它們。

雖然所示的簡短代碼段與dup2()行為非常相似,但基於本卷IEEE Std 1003.1-2001中定義的其他功能的符合實現要復雜得多。 最明顯的是信號捕獲函數的可能影響,可以在步驟之間調用並分配或釋放文件描述符。 阻止信號可以避免這種情況。

dup2()函數未標記為過時,因為它提供了fcntl()在類型不安全版本中提供的類型安全版本的功能。 它用於POSIX Ada綁定。

dup2()函數不用於關鍵區域作為同步機制。

在[EBADF]的描述中,fildes超出范圍的情況由fildes無效的給定情況涵蓋。 fildesfildes2的描述是不同的,因為與fildes2相關的唯一無效fildes2是它是否超出范圍; 也就是說,當進行dup2()調用時, fildes2是否引用打開的文件並不重要。

未來發展方向

沒有。

也可以看看

close()fcntl()open() ,IEEE Std 1003.1-2001的基本定義卷, <unistd.h>

改變歷史

首次發布在第1期中。來自SVID的第1期。

一個實際的例子是將輸出消息重定向到某些其他流,如某些日志文件。 以下是I / O重定向的示例代碼。
在這里參考原帖

#include <stdio.h>

main()
{
    int    fd;
    fpos_t pos;

    printf("stdout, ");

    fflush(stdout);
    fgetpos(stdout, &pos);
    fd = dup(fileno(stdout));
    freopen("stdout.out", "w", stdout);

    f();

    fflush(stdout);
    dup2(fd, fileno(stdout));
    close(fd);
    clearerr(stdout);
    fsetpos(stdout, &pos);        /* for C9X */

    printf("stdout again\n");
}

f()
{
printf("stdout in f()");
}

shell中的I / O重定向很可能是使用dup2 / fcnlt系統調用實現的。

我們可以使用dup2函數輕松模擬$program 2>&1 > logfile.log類型的重定向。

下面的程序重定向stdout和stderr .ie使用dup2模擬$program 2>&1 > output行為。

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

int
main(void){
    int close_this_fd;
    dup2(close_this_fd = open("output", O_WRONLY), 1);
    dup2(1,2);
    close(close_this_fd);
    fprintf(stdout, "standard output\n");
    fprintf(stderr, "standard error\n");
    fflush(stdout);
    sleep(100); //sleep to examine the filedes in /proc/pid/fd level.
    return;
}

vagrant@precise64:/vagrant/advC$ ./a.out
^Z
[2]+  Stopped                 ./a.out
vagrant@precise64:/vagrant/advC$ cat output
standard error
standard output
vagrant@precise64:/vagrant/advC$ ll /proc/2761/fd
total 0
dr-x------ 2 vagrant vagrant  0 Jun 20 22:07 ./
dr-xr-xr-x 8 vagrant vagrant  0 Jun 20 22:07 ../
lrwx------ 1 vagrant vagrant 64 Jun 20 22:07 0 -> /dev/pts/0
l-wx------ 1 vagrant vagrant 64 Jun 20 22:07 1 -> /vagrant/advC/output
l-wx------ 1 vagrant vagrant 64 Jun 20 22:07 2 -> /vagrant/advC/output

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM