[英]practical examples use dup or 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(或指示輸出或輸入源的變量)來處理輸入和輸出。 他們是stdin
, stdout
, stderr
,在整數他們是0
, 1
, 2
。 大多數函數如fprintf
或cout
都直接輸出到stdout
。
如果我們想重定向輸出,一種方法是給出,例如, fprintf
函數更多的參數指示in
和out
。
但是,有一種更優雅的方式:我們可以覆蓋默認文件ID,使它們指向我們想要接收輸出的文件。 dup
和dup2
在這種情況下完全正常工作。
現在讓我們從一個簡單的例子開始:假設我們想將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 :
這只是一個直觀的解釋,您可能需要檢查手冊頁或詳細信息。 實際上,我們在這里說“復制”,他們並沒有復制一切。
這里的文件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無效的給定情況涵蓋。 fildes
和fildes2
的描述是不同的,因為與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.