会计考友 发表于 2012-8-4 12:07:07

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

Linux认证辅导:形象的理解dup和dup2函数(3)
 二、重定向后恢复
  CU上有这样一个帖子,就是如何在重定向后再恢复原来的状态?首先大家都能想到要保存重定向前的文件描述符。那么如何来保存呢,象下面这样行么?
  int s_fd = STDOUT_FILENO;
  int n_fd = dup2(fd3, STDOUT_FILENO);
  还是这样可以呢?
  int s_fd = dup(STDOUT_FILENO);
  int n_fd = dup2(fd3, STDOUT_FILENO);
  这两种方法的区别到底在哪呢?答案是第二种方案才是正确的,分析如下:按照第一种方法,我们仅仅在“表面上”保存了相当于fd_t(按照我前面说的理解方法)中的index,而在调用dup2之后,ptr所指向的文件表项由于计数值已为零而被关闭了,我们如果再调用dup2(s_fd, fd3)就会出错(出错原因上面有解释)。而第二种方法我们首先做一下复制,复制后的状态如下图所示:
进程A的文件描述符表(after dup)
  ------------
  fd0 0 | p0
  ------------
  fd1 1 | p1 -------------》 文件表1 ---------》 vnode1
  ------------ /|
  fd2 2 | p2 /
  ------------ /
  fd3 3 | p3 -------------》 文件表2 ---------》 vnode2
  ------------ /
  s_fd 4 | p4 ------/
  ------------
  。.. 。..
  。.. 。..
  ------------
  调用dup2后状态为:
  进程A的文件描述符表(after dup2)
  ------------
  fd0 0 | p0
  ------------
  n_fd 1 | p1 ------------
  ------------ \
  fd2 2 | p2 \
  ------------ _\|
  fd3 3 | p3 -------------》 文件表2 ---------》 vnode2
  ------------
  s_fd 4 | p4 -------------》文件表1 ---------》 vnode1
  ------------
  。.. 。..
  。.. 。..
  ------------

 

会计考友 发表于 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);即可。下面是一个完整的例子程序:
  #define TESTSTR “Hello dup2\n”
  #define SIZEOFTESTSTR 11
  int main() {
  int fd3;
  int s_fd;
  int n_fd;
  fd3 = open(“testdup2.dat”, 0666);
  if (fd3 《 0) {
  printf(“open error\n”);
  exit(-1);
  }
/* 复制标准输出描述符 */
  s_fd = dup(STDOUT_FILENO);
  if (s_fd 《 0) {
  printf(“err in dup\n”);
  }
  /* 重定向标准输出到文件 */
  n_fd = dup2(fd3, STDOUT_FILENO);
  if (n_fd 《 0) {
  printf(“err in dup2\n”);
  }
  write(STDOUT_FILENO, TESTSTR, SIZEOFTESTSTR); /* 写入testdup2.dat中 */
  /* 重定向恢复标准输出 */
  if (dup2(s_fd, n_fd) 《 0) {
  printf(“err in dup2\n”);
  }
  write(STDOUT_FILENO, TESTSTR, SIZEOFTESTSTR); /* 输出到屏幕上 */
  return 0;
  }
  注意这里我在输出数据的时候我是用了不带缓冲的write库函数,如果使用带缓冲区的printf,则最终结果为屏幕上输出两行“Hello dup2”,而文件testdup2.dat中为空,原因就是缓冲区作怪,由于最终的目标是屏幕,所以程序最后将缓冲区的内容都输出到屏幕。
页: [1]
查看完整版本: Linux认证辅导:形象的理解dup和dup2函数(3)