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#一、fd#3的指向。
  • 使用重定向符時,指定文件描述符上打開文件的工做也是在shell運行命令程序前準備階段完成的。

對於my_dup2的測試,linux

    $  my_dup2   2   17shell

將在屏幕上輸出"It works!";bash

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

也將輸出"It works!";測試

    $    my_dup2   2   17  17>tmp.fooui

屏幕輸出"It words!",但tmp.foo中沒有任何記錄,這個例子模擬17已被佔有的情形。it

相關文章
相關標籤/搜索