Linux认证辅导:形象的理解dup和dup2函数(2)
8 H0 v3 X n* N一、单个进程内的dup和dup2
; i$ l& K& l% g% k! |$ g 假设进程A拥有一个已打开的文件描述符fd3,它的状态如下:4 W: k' c; B% V
进程A的文件描述符表(before dup2)& [ B1 C/ E/ W0 \) W$ G) n$ _- v
------------
! u, L- @; x m2 N3 Z: S$ O4 ] fd0 0 | p0* @# t& C) A# }. O8 Z2 M8 z# }. s& B
------------
; G: d, B% ~& c1 E; O fd1 1 | p1 -------------》 文件表1 ---------》 vnode13 {% F5 {9 S+ `5 J$ ?2 o
------------
/ E( ^2 `! a* {7 d) d/ B, ~- J; L+ y fd2 2 | p23 [, L- s' S9 r( a' ]
------------ D% V) I$ u; i$ f( u7 B F& C% }
fd3 3 | p3 -------------》 文件表2 ---------》 vnode2/ t; Z. G6 }, o5 b' _" [
------------3 n% g, z8 L. m9 `4 A) P
。。. 。。.
" x7 L: s1 f9 a, {' C 。。. 。。.
* {* V* s8 t/ ?; a+ W ------------
5 b( m5 J8 {0 V 经下面调用:
# A+ i Q$ D( {' v7 U) Y- z# o n_fd = dup2(fd3, STDOUT_FILENO);后进程状态如下:) l( D; q8 ^7 a: g' z
进程A的文件描述符表(after dup2)
3 x! X9 l* s+ k7 D$ b: Z9 Q ------------* i2 O4 s+ q% V1 {& |
fd0 0 | p0
7 K* k- H3 T; h ------------
9 _# S1 {$ n1 R- L L. B n_fd 1 | p1 ------------
, s1 S& K5 m6 Z$ W5 [( H* c* J ------------ \1 `) m# l2 S3 ^' f6 E% X5 c) N
fd2 2 | p2 \/ w8 n* \1 j2 I$ i3 ~3 `, y3 A4 r
------------ _\|" E3 c- a/ ]' U! w
fd3 3 | p3 -------------》 文件表2 ---------》 vnode25 B6 r% t# F- C( d
------------# s4 n$ J6 X: `
。。. 。。.$ q% C* |: U( l8 n. u/ b1 L. n
。。. 。。.
! n8 C( p6 l' |+ c ------------
6 T: J x1 N. e4 q. m9 f( z 解释如下:8 w: p r2 f" l) u
n_fd = dup2(fd3, STDOUT_FILENO)表示n_fd与fd3共享一个文件表项(它们的文件表指针指向同一个文件表项),n_fd在文件描述符表中的位置为 STDOUT_FILENO的位置,而原先的STDOUT_FILENO所指向的文件表项被关闭,我觉得上图应该很清晰的反映出这点。按照上面的解释我们就可以解释CU中提出的一些问题:
. M/ C0 k, r, E# A( g (1) “dup2的第一个参数是不是必须为已打开的合法filedes?” -- 答案:必须。- W" Y* Q. k' g, S4 l0 W
(2) “dup2的第二个参数可以是任意合法范围的filedes值么?” -- 答案:可以,在Unix其取值区间为[0,255]。
3 {0 O7 ^* s% U; ~1 e2 x% c另外感觉理解dup2的一个好方法就是把fd看成一个结构体类型,就如上面图形中画的那样,我们不妨把之定义为:3 K3 h" m: w, z5 _6 R+ [! i" E$ i
struct fd_t {0 {6 ?! Z% U8 i0 N; f4 f
int index;. ]5 l H8 u2 M) j% C, ~' [' y" Z
filelistitem *ptr;1 v2 k$ |/ ^6 ?% N$ O3 f5 D
};
1 X* F3 s7 i( j 然后dup2匹配index,修改ptr,完成dup2操作。
- n7 f* ~0 r9 Y4 Q 在学习dup2时总是碰到“重定向”一词,上图完成的就是一个“从标准输出到文件的重定向”,经过dup2后进程A的任何目标为STDOUT_FILENO的I/O操作如printf等,其数据都将流入fd3所对应的文件中。下面是一个例子程序:
! s8 b! _0 f( K* u2 i$ D. ? #define TESTSTR “Hello dup2\n”2 t7 K7 f1 C" b0 o4 @; u
int main() {& O0 i3 s0 @0 T
int fd3;
7 M- X I G$ v1 Y9 {3 Q1 Y# i) { fd3 = open(“testdup2.dat”, 0666);' b# p/ M, b5 v+ \' @% O
if (fd 《 0) {3 u: g( B7 q8 Q/ p) M
printf(“open error\n”); D5 |" e3 {" n) O5 Q. E
exit(-1);
2 J" U0 k, I" G# Q' E }& H' w. O1 d6 q: B
if (dup2(fd3, STDOUT_FILENO) 《 0) {
3 u) L' Z8 u( ?* e; ?/ z printf(“err in dup2\n”);
1 m( W9 e$ y, Y }" O' q0 j9 Q& Y- ~8 V+ k
printf(TESTSTR);
0 D7 a' }4 ^( A# ?) Y return 0;9 N0 f, L9 I5 A/ U! \
}
, y9 r* J/ C/ ~8 r+ C; S" L 其结果就是你在testdup2.dat中看到“Hello dup2”。 |