a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 86|回复: 1

[综合辅导] Linux认证辅导:形象的理解dup和dup2函数(3)

[复制链接]
发表于 2012-8-4 12:07:07 | 显示全部楼层 |阅读模式
Linux认证辅导:形象的理解dup和dup2函数(3)
8 d. h2 e2 t; c8 D" n+ z7 i7 ~ 二、重定向后恢复
8 B6 @$ F' E! X/ E7 e7 D  CU上有这样一个帖子,就是如何在重定向后再恢复原来的状态?首先大家都能想到要保存重定向前的文件描述符。那么如何来保存呢,象下面这样行么?9 L/ M& W5 S, E& Y# g- `8 h
  int s_fd = STDOUT_FILENO;5 n) D' w2 x* n6 s- `- R" }
  int n_fd = dup2(fd3, STDOUT_FILENO);& ~- g2 q$ Y7 u1 m% G" |
  还是这样可以呢?
2 |( C" L7 j  w$ T% U( p# c5 }  int s_fd = dup(STDOUT_FILENO);7 a4 t0 X! ?* g$ A4 L5 W. V
  int n_fd = dup2(fd3, STDOUT_FILENO);
( {5 i& X$ c7 Y3 L2 v. F. ~  这两种方法的区别到底在哪呢?答案是第二种方案才是正确的,分析如下:按照第一种方法,我们仅仅在“表面上”保存了相当于fd_t(按照我前面说的理解方法)中的index,而在调用dup2之后,ptr所指向的文件表项由于计数值已为零而被关闭了,我们如果再调用dup2(s_fd, fd3)就会出错(出错原因上面有解释)。而第二种方法我们首先做一下复制,复制后的状态如下图所示:
* G4 V+ P$ ?8 o6 V! D进程A的文件描述符表(after dup)9 `0 n0 m/ C+ O3 ~4 H' @" Z
  ------------  p+ h+ K- k# r+ P: S
  fd0 0 | p0+ Q0 _5 w8 m0 P/ F& e: Y) ~
  ------------
! {" y) s8 Q0 L0 d9 ~+ I9 `8 E6 b  fd1 1 | p1 -------------》 文件表1 ---------》 vnode1' W  V$ G4 L9 K' ]9 I* \
  ------------ /|
& t3 Q. M/ W- w$ O6 Q: [) i  fd2 2 | p2 /
7 X/ v! [9 @7 f" _$ @( D& b  ------------ /: t* c% _. X. c$ l! _; f
  fd3 3 | p3 -------------》 文件表2 ---------》 vnode2
8 ?1 r% O6 Q5 ^) e. |- ~4 w  ------------ /
$ B2 d+ }0 \4 D9 J$ Z# X& S$ M( d  s_fd 4 | p4 ------/
- B7 T3 l# b) F* x( ]  ------------" n6 p5 b  |, o& M+ R4 B
  。.. 。..
" O+ W4 y2 X/ x- P4 t3 @& Q$ C/ Y  。.. 。..
0 d* P, `: L/ K" p  ------------# N4 v7 @% D9 n# l9 T5 l6 A
  调用dup2后状态为:* ^% Y' i" R3 _5 }: |
  进程A的文件描述符表(after dup2)8 J* K) T, d* t' h5 T1 j
  ------------
" Q% ]. j- c4 Q& ^8 k  fd0 0 | p0
( M1 O( q) A4 z1 y  ------------& {0 p- C3 [  Q  {
  n_fd 1 | p1 ------------
& I) L, e! J4 K: S! g% P; T  ------------ \
; `4 B- b. w" V$ p6 v' D* }) S! z  fd2 2 | p2 \2 l3 I# u5 `5 a3 }3 ~! B/ l
  ------------ _\|, l* P# X7 K4 D/ U) O" D
  fd3 3 | p3 -------------》 文件表2 ---------》 vnode2
: e- b9 c# E: C  ------------
3 z" [+ U( ]! Z& E6 R) J2 ?7 g  s_fd 4 | p4 -------------》文件表1 ---------》 vnode1
! @1 d7 M% A, V( j: I3 y  ------------
; n" v! P  H6 w% i# Y  。.. 。..
( E! ~/ b: L: Y! y" W9 ^( p7 X  。.. 。..
; z* h8 x- X& A, L  ------------
4 q& d/ V+ e/ b1 _1 K1 A7 t( W9 G0 j/ m2 U+ M0 O
 
回复

使用道具 举报

 楼主| 发表于 2012-8-4 12:07:08 | 显示全部楼层

Linux认证辅导:形象的理解dup和dup2函数(3)

 dup(fd)的语意是返回的新的文件描述符与fd共享一个文件表项。就如after dup图中的s_fd和fd1共享文件表1一样。</p>  确定第二个方案后重定向后的恢复就很容易了,只需调用dup2(s_fd, n_fd);即可。下面是一个完整的例子程序:8 P5 E& b8 p6 `( B, W
  #define TESTSTR “Hello dup2\n”
/ d9 m7 h: ]4 x' B; E  #define SIZEOFTESTSTR 11
( x: D8 b+ d) Z3 {) w- \  int main() {8 w. s( u$ g" ~$ a- n& p0 t+ L0 ?/ n
  int fd3;
0 I' z' @  o. e2 w( r  int s_fd;
$ B, c8 Q( |5 X/ y$ h" @  int n_fd;* c7 d7 y+ N" X) i
  fd3 = open(“testdup2.dat”, 0666);
7 u/ N- x! B9 C' ^' Q2 s# r  if (fd3 《 0) {1 I# P0 g7 ~8 p( ]  }% d* e
  printf(“open error\n”);
5 M  v( `. g6 n* M  exit(-1);
, G; g3 n, j" I' \) h  }
: u, U' f- z) H/ \/* 复制标准输出描述符 */, R; V5 [9 h: u: U( I
  s_fd = dup(STDOUT_FILENO);" S& n; j1 d1 N) U: Y: x; e
  if (s_fd 《 0) {# }7 j# S% Z9 {5 u  _
  printf(“err in dup\n”);4 c2 }; f% t/ d2 [1 V
  }" A& [: g  A- c- n" D( n6 R
  /* 重定向标准输出到文件 */
( y6 G& I$ Z) i8 e! e  n_fd = dup2(fd3, STDOUT_FILENO);. F* g, q% i' h9 S9 {( S, f
  if (n_fd 《 0) {4 E! W3 j4 p( l
  printf(“err in dup2\n”);
; V: V: y6 K: g9 Y  }- Q* |* m/ [0 S" r
  write(STDOUT_FILENO, TESTSTR, SIZEOFTESTSTR); /* 写入testdup2.dat中 */
  F8 ], k' W- T7 v3 F1 _( G  /* 重定向恢复标准输出 */: H5 F; `* W/ `( P$ R+ _/ V' ~
  if (dup2(s_fd, n_fd) 《 0) {3 p# R% a  N* W
  printf(“err in dup2\n”);' |: W' r* e4 H4 _
  }$ u, x% E0 \. h3 I
  write(STDOUT_FILENO, TESTSTR, SIZEOFTESTSTR); /* 输出到屏幕上 */
+ {' ]2 W" l. V4 v" \$ m  return 0;' X* y7 I$ G7 {) K! Q3 Q6 ]/ G
  }+ T- P+ J! v: J7 }, d
  注意这里我在输出数据的时候我是用了不带缓冲的write库函数,如果使用带缓冲区的printf,则最终结果为屏幕上输出两行“Hello dup2”,而文件testdup2.dat中为空,原因就是缓冲区作怪,由于最终的目标是屏幕,所以程序最后将缓冲区的内容都输出到屏幕。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-5-18 01:21 , Processed in 0.419206 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表