习题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已被占有的情形。

APUE习题3.2用dup实现dup2以及shell中重定向符号的使用的更多相关文章

  1. dup和dup2应用实例(dup跟APUE有出入,close+dup=dup2?)

    dup/dup2函数 有时我们希望把标准输入重定向到一个文件,或者把标准输出重定向到一个网络连接. dup()与dup2()能对输入文件描述符进行重定向. 函数原型如下: dup函数创建一个新的文件描 ...

  2. linux之dup和dup2函数解析

    1. 文件描述符在内核中数据结构在具体说dup/dup2之前,我认为有必要先了解一下文件描述符在内核中的形态.一个进程在此存在期间,会有一些文件被打开,从而会返回一些文件描述符,从shell中运行一个 ...

  3. Linux进程间通信(三):匿名管道 popen()、pclose()、pipe()、close()、dup()、dup2()

    在前面,介绍了一种进程间的通信方式:使用信号,我们创建通知事件,并通过它引起响应,但传递的信息只是一个信号值.这里将介绍另一种进程间通信的方式——匿名管道,通过它进程间可以交换更多有用的数据. 一.什 ...

  4. dup和dup2用法小结

    今天和同学探讨了一下关于重定向输出到文件的问题,其中需要用到dup和dup2函数,因此来小小的总结一下. 首先来man一下: dup直接返回一个新的描述符和原来的描述符一样代表同一个资源,描述符的值就 ...

  5. Linux内核分析:dup、dup2的实现

    一.首先需要看一下这两个函数的作用: #include <unistd.h> int dup(int oldfd); int dup2(int oldfd, int newfd); 根据m ...

  6. dup和dup2函数

    下面两个函数都可用来复制一个现存的文件描述符: #include<unistd.h> int dup(int filedes); int dup2(int filedes,int file ...

  7. dup和dup2函数以及管道的实现

    疑问:管道应该不是这样实现的,因为这要求修改程序的代码 dup和dup2也是两个非常有用的调用,它们的作用都是用来复制一个文件的描述符.它们经常用来重定向进程的stdin.stdout和stderr. ...

  8. dup和dup2详解

    C语言中dup和dup2函数的不同和使用 发表时间: 2012年11月15日 | 作者: 陈杰斌 | 所属分类: C语言 | 评论: 0 | 浏览: 1024 在unix高级编程中有介绍dup和dup ...

  9. Linux系统编程--文件描述符的复制dup()和dup2()【转】

    本文转载自:http://blog.csdn.net/tennysonsky/article/details/45870459 dup() 和 dup2() 是两个非常有用的系统调用,都是用来复制一个 ...

随机推荐

  1. 通过类名或者jar名查询所在jar包

    一.问题 例如我想查看一下FilterSecurityInterceptor的源码,但是我不知道它在maven依赖中的哪个jar包中 二.解决方案 http://www.findmaven.net/ ...

  2. Golang中的三个点

    之前提到了把一个切片追加到另外一个切片时使用到了... 今天我们好好研究一下这三个点,博客写着写着又成了,回字有四种写法 ...第一种用法,可变长的参数 package main import &qu ...

  3. Python列表详解

    #列表:增,删,改,查.names=['N0','N1','N2',['EX1','EX2'],'N3'] '''#------------------------------------------ ...

  4. redis 一些操作命令

    # 删除laravel keyredis-cli -h 10.9.103.15 -a password keys "laravel*" | xargs redis-cli -h 1 ...

  5. 【APP测试(Android)】--功能

  6. OpenCV图像分割1

    1.基于阈值 1.1原理 灰度阈值化,假设输入图像为f,输出图像为g,则阈值化公式如下: g(i,j)=1  当f(i,j)>=T g(i,j)=0 当f(i,j)<T 1.2适用范围 当 ...

  7. C++获取工程路径、exe路径

    编码过程中有时候会用到获取工程所在路径或者exe所在的路径信息,这里稍微记录下. 获取工程路径 char pBuf[MAX_PATH]; //存放路径的变量 GetCurrentDirectory(M ...

  8. C#语言不常用语法笔记

    只看过3天C#语法书,了解个大概,与C++等不同之处,或者看开源遇到一些奇异用法,记录一下,脑子不够用的情况下,还是记笔记靠谱. ==================== 顺便吐槽下,这年头得会各种编 ...

  9. C++中的return和exit区别

    在main函数中,return和exit经常混用,两者的一个区别:return会执行statck unwinding,而exit不会.如果触发了信号,exit也同样不会做stack unwinding ...

  10. 三.mysql表的完整性约束

    mysql表的完整性约束 什么是约束 not null    不能为空的 unique      唯一 = 不能重复 primary key 主键 = 不能为空 且 不能重复 foreign key ...