APUE习题3.2用dup实现dup2以及shell中重定向符号的使用

习题3.2的要求是不使用fcntl()而编写一个同dup2()功能相同的函数。直觉上是不断使用dup()直到返回指定的文件描述符。
#include <stdio.h>
#include <stdlib.h>
#define OPEN_MAX 63

int my_dup2(int filedes,int filedes2);

int
main(int argc, char* argv[])
{
  int fd,fd2;
  char buf[] = "It work!\n";

  if(argc != 3)
    err_quit("Usage: %s <filedes#> <filedes2#>",argv[0]);
 
  fd = atoi(argv[1]);
  fd2 = atoi(argv[2]);
  my_dup2(fd, fd2);
  printf("fd#%d -> fd#%d\n", fd2, fd);
  if( write(fd2, buf, 9) != 9)
    err_sys("write error");

  exit(0);
}


int
my_dup2(int filedes,int filedes2)
{
  int fd_rec[OPEN_MAX];
  int fd,i,n;
 
  if( filedes == filedes2)  //模拟dup2的行为,当filedes2等于filedes时,直接返回filedes即可
    return filedes;

  for(n=0 ; (fd=dup(filedes)) < filedes2; n++){  //由于dup总返回当前可用文件描述符的最小值,因此要不断尝试
    fd_rec[n] = fd;  //保存尝试的文件描述符,以便后面关闭
  }
  if( fd != filedes2)  //退出循环的条件也可能由于filedes2已被占用,这时dup2先将原先占有filedes2的文件关掉,此时dup肯定是filedes2
  {
    close(filedes2);
    fd = dup(filedes);
  }
  //关闭打开的非目标文件描述符
  for(i=0; i<n; i++)
    close(fd_rec[i]);
 
  return fd;
}
 
linux bash shell中常常会使用到命令的输入输出重定向符号。例如,《APUE》中程序3-4的使用
       $  a.out  <  /dev/tty     //将程序输入重定向为/dev/tty
       $  a.out  >  tmp.foo      //将程序输出重定向至文件temp.foo
       $  a.out  2>>  temp.foo     //在文件描述符2上打开文件temp.foo以供添写,通常程序出错时会向fd#2上写入相关错误信息
       $  a.out  5<>temp.foo     //在fd#5上打开文件temp.foo以供读、写
文件描述符通常有几个值是被系统保留使用的,默认地,0-标准输入,1-标准输出,2-错误输出。
  • 在没有这些重定向符号时,shell会在运行命令程序前的准备阶段,初始化fd#0、fd#1、fd#3的指向。
  • 使用重定向符时,指定文件描述符上打开文件的工作也是在shell运行命令程序前准备阶段完成的。

对于my_dup2的测试,

    $  my_dup2   2   17

将在屏幕上输出"It works!";

    $  my_dup2   7 17  7<>/dev/fd/1

也将输出"It works!";

    $    my_dup2   2   17  17>tmp.foo

屏幕输出"It words!",但tmp.foo中没有任何记录,这个例子模拟17已被占有的情形。

posted @ 2015-02-08 21:53  l3sl!e  阅读(299)  评论(0编辑  收藏  举报