對(duì)于 Dup2 的理解:
源代碼:
?
1
#include <unistd.h>
2
#include <stdio.h>
3
#include <stdlib.h>
4
#include <
string
.h>
5
#include <time.h>
6
7
#define
MSGSIZE 20
8
#define
READ 0
9
#define
WRITE 1
10
11
int
main(
int
argc,
char
const
*
argv[])
12
{
13
int
p[
2
], bytes, res, c;
14
char
inbuf[
10240
];
15
int
pid;
16
printf(
"
%c
"
,
11
);
17
if
(pipe(p) == -
1
){
//
creat the pipe , if pipe is built failed , exit .
18
perror(
"
pip call
"
);
19
exit(
1
);
20
}
21
pid =
fork();
22
if
(pid !=
0
){
//
creat parent pid and child pid.
23
close(p[READ]);
//
close parent pipe read
24
dup2(p[WRITE],
1
);
25
close(p[WRITE]);
//
close parent pipe write
26
execlp(argv[
1
], argv[
1
], NULL);
27
}
28
else
{
29
30
close(p[WRITE]);
//
close child pipe write
31
32
dup2(p[READ],
0
);
33
34
close(p[READ]);
//
close child pipe read
35
36
execlp(argv[
2
], argv[
2
], NULL);
37
}
38
return
0
;
39
}
?
通過(guò)命令行輸出:
./a.out “l(fā)s” “ps”
僅僅在終端執(zhí)行了 ps 的命令, 而沒(méi)有看到 ls 命令的結(jié)果。
因此,開(kāi)始走入了第一個(gè)誤區(qū):父進(jìn)程沒(méi)有執(zhí)行
通過(guò)調(diào)試 在父進(jìn)程執(zhí)行 if 條件中加入以下代碼:
if(pid != 0){
printf("4556\n");
close(p[READ]);
dup2(p[WRITE], 1);
close(p[WRITE]);
printf("4556\n");
execlp(argv[1], argv[1], NULL);
}
加入了 2 個(gè) printf , 但是只有 dup2 上面的 printf 結(jié)果輸出到屏幕上,因此我注釋了 dup2(p[WRITE], 1); 結(jié)果在父進(jìn)程 if 語(yǔ)句中的 dup2 后面的命令都執(zhí)行并且輸出到屏幕上了。通過(guò)查找 dup2 命令發(fā)現(xiàn)了重定向的強(qiáng)大之處。
先解釋下 dup2 命令,
int dup2(int filedes, int filedes2);
說(shuō)明:
用 dup2 則可以用 filedes2 參數(shù)指定新描述符的數(shù)值。如果 filedes2 已經(jīng)打開(kāi),則先將其關(guān)閉。如若 filedes 等于 filedes2 ,則返回 filedes2 ,而不關(guān)閉它。
dup2(p[WRITE], 1); 這句話可以理解為將標(biāo)準(zhǔn)輸出重定向到 p[WRITE], 因此在這句話后面的所有 printf 語(yǔ)句打印或者 exec 執(zhí)行的內(nèi)容都輸入到了 p[WRITE] 中。剛開(kāi)始有個(gè)迷惑,就是既然已經(jīng) close ( 1 )了,為什么還能輸入到 p[WRITE] 中,通過(guò)自己的直覺(jué)判斷,應(yīng)當(dāng)是 close(1) 關(guān)閉了屏幕的輸出,但是它有緩沖區(qū)保存 printf 打印出的內(nèi)容,并且由于重定向的關(guān)系,輸進(jìn)了 p[WRITE] 中。
?
代碼:
?
1
#include <unistd.h>
2
#include <stdio.h>
3
#include <stdlib.h>
4
#include <
string
.h>
5
#include <time.h>
6
7
#define
MSGSIZE 20
8
#define
READ 0
9
#define
WRITE 1
10
11
int
main(
int
argc,
char
const
*
argv[])
12
{
13
int
p[
2
], bytes, res, c;
14
char
inbuf[
10240
];
15
int
pid;
16
printf(
"
%c
"
,
11
);
17
if
(pipe(p) == -
1
){
//
creat the pipe , if pipe is built failed , exit .
18
perror(
"
pip call
"
);
19
exit(
1
);
20
}
21
pid =
fork();
22
if
(pid !=
0
){
//
creat parent pid and child pid.
23
close(p[READ]);
//
close parent pipe read
24
dup2(p[WRITE],
1
);
25
close(p[WRITE]);
//
close parent pipe write
26
printf(
"
123!\n
"
);
27
execlp(argv[
1
], argv[
1
], NULL);
28
perror(
"
execlp
"
);
//
error output
29
}
30
else
{
31
while
(
1
){
32
res = read(p[READ], inbuf,
10240
);
33
if
(res>
0
)
34
printf(
"
%s\n
"
, inbuf);
35
break
;
36
}
37
38
close(p[WRITE]);
//
close child pipe write
39
40
dup2(p[READ],
0
);
41
42
close(p[READ]);
//
close child pipe read
43
44
execlp(argv[
2
], argv[
2
], NULL);
45
}
46
return
0
;
47
}
?
?
?
通過(guò)在子進(jìn)程中用 while(1) 循環(huán)讀取 p[READ] 內(nèi)容,發(fā)現(xiàn)讀出了父進(jìn)程本應(yīng)在屏幕上打印的內(nèi)容,因此父進(jìn)程是執(zhí)行了所有命令行,只是通過(guò)重定向命令存到了 p[WRITE] 管道中。
由于有 dup2(p[READ], 0) 命令,因此猜測(cè)標(biāo)準(zhǔn)輸入的文件描述符定向到了 p[READ] , 因此如果猜測(cè)沒(méi)錯(cuò),通過(guò) getchar() 讀取文件標(biāo)準(zhǔn)輸入并把 P[READ] 的內(nèi)容輸出到屏幕上則證明我猜想沒(méi)錯(cuò)。
代碼 :
?
1
#include <unistd.h>
2
#include <stdio.h>
3
#include <stdlib.h>
4
#include <
string
.h>
5
#include <time.h>
6
7
#define
MSGSIZE 20
8
#define
READ 0
9
#define
WRITE 1
10
11
int
main(
int
argc,
char
const
*
argv[])
12
{
13
int
p[
2
], bytes, res, c;
14
char
inbuf[
10240
];
15
int
pid;
16
printf(
"
%c
"
,
11
);
17
if
(pipe(p) == -
1
){
//
creat the pipe , if pipe is built failed , exit .
18
perror(
"
pip call
"
);
19
exit(
1
);
20
}
21
pid =
fork();
22
if
(pid !=
0
){
//
creat parent pid and child pid.
23
close(p[READ]);
//
close parent pipe read
24
dup2(p[WRITE],
1
);
25
close(p[WRITE]);
//
close parent pipe write
26
printf(
"
123!\n
"
);
27
execlp(argv[
1
], argv[
1
], NULL);
28
perror(
"
execlp
"
);
//
error output
29
}
30
else
{
31
//
while(1){
32
//
res = read(p[READ], inbuf, 10240);
33
//
if(res>0)
34
//
printf("%s\n", inbuf);
35
//
break;
36
//
}
37
38
close(p[WRITE]);
//
close child pipe write
39
40
dup2(p[READ],
0
);
41
while
((c=getchar()) != -
1
){
42
printf(
"
%c
"
, c);
43
}
44
close(p[READ]);
//
close child pipe read
45
46
execlp(argv[
2
], argv[
2
], NULL);
47
}
48
return
0
;
49
}
?
通過(guò)在 dup2(p[READ], 0) 后面 while 循環(huán)讀入輸入流輸入的字符并且打印出來(lái), 發(fā)現(xiàn)結(jié)果果然是 p[READ] 的內(nèi)容,猜疑沒(méi)錯(cuò)。
為了更清楚的理解 dup2 的重定向含義,想理解 dup2(fd,0) 和 dup2(0,fd) 功能相同嗎?
為了得到答案,找些資料發(fā)現(xiàn),答案是不同。
?
測(cè)試代碼:
1
#include <stdio.h>
2
#include <unistd.h>
3
#include <fcntl.h>
4
5
#define
BUFMAXSIZE 4096
6
7
int
main(
int
argc,
char
*
argv[])
8
{
9
int
fd;
10
int
n;
11
char
buf[BUFMAXSIZE];
12
int
fs;
13
fs = open(
"
test
"
, O_RDWR);
14
if
((fd = open(
"
duan
"
, O_RDWR )) == -
1
)
15
{
16
perror(
"
open error!
"
);
17
return
(
1
);
18
}
19
20
dup2(fd,
1
);
//
dup2(0,fd);
21
22
while
((n = read(fs, buf, BUFMAXSIZE)) >
0
)
23
{
24
printf(
"
begin to read...\n
"
);
25
if
(write(STDOUT_FILENO, buf, n) !=
n)
26
{
27
perror(
"
write error!
"
);
28
return
(
1
);
29
}
30
printf(
"
end to write...\n
"
);
31
}
32
if
(n <
0
)
33
{
34
perror(
"
read error
"
);
35
return
(
1
);
36
}
37
38
return
0
;
39
}
?
?
dup(fd, 0) 這段代碼測(cè)試, 打印出了 duan 文件里面的內(nèi)容。
之后創(chuàng)建個(gè)文件 Levi 里面寫(xiě)和 duan 文件不同的內(nèi)容。
通過(guò) ./a. out < Levi 輸出:
第一個(gè)輸出是 dup(fd, 0) 輸出了 Duan 文件的內(nèi)容。即是 fd 的內(nèi)容
第二個(gè)輸出是 dup(0, fd) 輸出了 Levi 文件的內(nèi)容。即是 通過(guò)文件重定向到標(biāo)準(zhǔn)輸入的內(nèi)容。
從圖中的輸出結(jié)果已經(jīng)可以看到兩者的區(qū)別了。
第一種 dup2(fd,0) 之前已經(jīng)將 fd 初始化指向到文本 Duan 了,
并且不會(huì)被后面的代碼所修改。
第二種 dup2(0,fd) 則將 fd 重新指向到文件描述符 0 所代表的文件(即終端標(biāo)準(zhǔn)輸入)了。
那么可以看到,程序的執(zhí)行中不會(huì)再讀取 Duan 文件了。
而是進(jìn)入了一種交互模式。
另外,這時(shí)“輸入重定向”也可以生效了。
文件描述符 0 被 “ <” 重定向到 Duan 了
所以,這里直接輸出了該文本的內(nèi)容。
dup2(fd,0) 相當(dāng)于“輸入重定向”的功能,
dup2(0,fd) 不是表示 fd 所指的文件接收來(lái)自終端的輸入,因?yàn)椋? fd 已經(jīng)不再指向原來(lái)的那個(gè)文件了。
它和文件描述符 0 已經(jīng)在共享同一個(gè)文件表項(xiàng)(即指向終端標(biāo)準(zhǔn)輸入的那個(gè)表項(xiàng))了。
“ 輸出重定向”的功能可以用 dup2(fd ,1) 替代。
dup2(fd,1) 和 dup2(1,fd) 也是大同小異。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元

