Linux认证辅导:形象的理解dup和dup2函数(2)( A+ I7 \ H9 o
一、单个进程内的dup和dup2
2 ?: E! j+ a! a. |# T 假设进程A拥有一个已打开的文件描述符fd3,它的状态如下:0 ]( T: Q7 I" o5 _# M
进程A的文件描述符表(before dup2)
) T+ Z& n* b" Z# z ------------. s3 ^$ K) O, Q# u- j% q
fd0 0 | p0, x; t+ I6 W" |2 F) f" V! s$ ~2 k
------------
1 z5 g3 P# m9 k" b5 ~" S* t fd1 1 | p1 -------------》 文件表1 ---------》 vnode1
" h' m3 D2 E0 P+ m1 h0 N2 f ------------
5 ~' Z) |) }1 q8 V! }* J: a fd2 2 | p2& g8 _. {( @: }/ s/ B6 D
------------1 R! w: m4 Y8 [) c6 g
fd3 3 | p3 -------------》 文件表2 ---------》 vnode2
: F' r" v0 m# V ------------. N _* W; P D/ Z0 `3 H
。。. 。。.. W: N# w/ a( A
。。. 。。., `& q* |/ I2 A8 l. y( O% t
------------2 V4 o* J$ `5 i3 ]
经下面调用:+ I$ c- ~ D9 v' E0 ^1 d( k
n_fd = dup2(fd3, STDOUT_FILENO);后进程状态如下:8 I. |# e, H6 c) L! G' g6 u
进程A的文件描述符表(after dup2)
# d+ C/ h7 [3 {: H2 A9 f ------------4 G Y& Y* Z, M v6 }
fd0 0 | p0: Z+ n' o) [9 D% C
------------7 o8 K0 w* f( @( F+ q; R
n_fd 1 | p1 ------------+ ?* y0 P3 ~" @6 i ?% [3 i) L
------------ \: {8 N. t( { C8 m" q# k
fd2 2 | p2 \1 U6 P+ t a* X8 f
------------ _\|
9 A' b7 W% V0 [ fd3 3 | p3 -------------》 文件表2 ---------》 vnode2" I4 |) _% s+ f# X- Y- ] T+ ^+ {
------------, B& J2 z; l9 l4 i6 r& f: ^8 D- d
。。. 。。.6 m" A9 q7 ~& H Z+ v
。。. 。。.
! a5 P4 ~, l* M3 H8 M: Q ------------
& M k/ E$ _, C, N: S/ f8 W 解释如下:
# V* ]8 M* I( I+ m9 f n_fd = dup2(fd3, STDOUT_FILENO)表示n_fd与fd3共享一个文件表项(它们的文件表指针指向同一个文件表项),n_fd在文件描述符表中的位置为 STDOUT_FILENO的位置,而原先的STDOUT_FILENO所指向的文件表项被关闭,我觉得上图应该很清晰的反映出这点。按照上面的解释我们就可以解释CU中提出的一些问题:
1 G( y+ H5 U. ^# h (1) “dup2的第一个参数是不是必须为已打开的合法filedes?” -- 答案:必须。' w0 {6 k- h' {6 B1 p
(2) “dup2的第二个参数可以是任意合法范围的filedes值么?” -- 答案:可以,在Unix其取值区间为[0,255]。
& ~/ Q6 v4 a% O# W另外感觉理解dup2的一个好方法就是把fd看成一个结构体类型,就如上面图形中画的那样,我们不妨把之定义为:+ z. e9 ]. Q, ~% o1 m5 W7 H
struct fd_t {
3 k s s: T: g! U3 p int index;& Z( }# }6 _. w9 _, M
filelistitem *ptr;
: H/ V$ h0 x( e: k };* A6 }3 I! f C* |
然后dup2匹配index,修改ptr,完成dup2操作。. c1 r% \1 b. O
在学习dup2时总是碰到“重定向”一词,上图完成的就是一个“从标准输出到文件的重定向”,经过dup2后进程A的任何目标为STDOUT_FILENO的I/O操作如printf等,其数据都将流入fd3所对应的文件中。下面是一个例子程序: z! `: `: W: }4 ^3 J' }* H
#define TESTSTR “Hello dup2\n”
2 E" Z8 @8 _! j0 x( g0 z1 v7 ~ int main() {# Q/ N' y; V0 I" g2 w
int fd3;- R/ u5 e$ w/ O$ }7 u7 u
fd3 = open(“testdup2.dat”, 0666);
4 V6 n* U! n1 o if (fd 《 0) {
0 j6 i6 K7 Z" `, v printf(“open error\n”);/ R7 e! I G& |- W$ E" T
exit(-1);
& ^; f. Y) o$ u( I8 C& x8 g# T ^ }
: ~* f: T( M% |- P. d5 a if (dup2(fd3, STDOUT_FILENO) 《 0) {
7 O: u& C0 r0 E! v. X! l" U0 ]8 I printf(“err in dup2\n”);- ~. d8 T% v. B# t J/ C
}
9 |- o( P" L# |* W) K printf(TESTSTR);
, |8 l- k2 F" e8 Y return 0;
8 q" V3 I: Y9 Z! Q2 R }! [2 q! i, b$ ?) i, ?4 X9 O
其结果就是你在testdup2.dat中看到“Hello dup2”。 |