5.1 dup 函数---复制文件描述符

5.1.1 简单cat实现及输入输出重定向

  io.c

 #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "io.h"
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h> #define BUFFER_LEN 1024 /* 文件的读写拷贝 */
void copy(int fdin, int fdout)
{
char buff[BUFFER_LEN];
ssize_t size; // printf("file length: %ld\n", lseek(fdin, 0L, SEEK_END));//将文件定位到文件尾部,偏移量为0L
// lseek(fdin, 0L, SEEK_SET);// 定位到文件开头 while((size = read(fdin, buff, BUFFER_LEN)) > ) { //从 fdin 中读取 BUFFER_LEN 个字节存放入 buff 中
// printf("current: %ld\n", lseek(fdin, 0L, SEEK_CUR)); if(write(fdout, buff, size) != size) {
fprintf(stderr, "write error: %s\n", strerror(errno));
exit();
}
}
if(size < ) {
fprintf(stderr, "read error:%s\n", strerror(errno));
exit(); // 相当于 return 1;
}
}

  cat.c

 #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "io.h"
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h> int main(int argc, const char *argv[])
{
int fd_in = STDIN_FILENO;
int fd_out = STDOUT_FILENO;
int i; for(i = ; i < argc; i++) {
fd_in = open(argv[i], O_RDONLY);
if(fd_in < ) {
perror("open error");
continue;
} copy(fd_in, fd_out);
close(fd_in);
} if(argc == )
copy(fd_in, fd_out); return ;
}

  编译:gcc -o bin/cat -Iinclude src/io.c src/cat.c

  调试:

  

  

  

  cat 的作用就输入和输出的重定向功能,而 dup 和 dup2 就是用来完成此功能的。

5.1.2 dup 和 dup2 函数说明

 #include<unistd.h>
int dup (int oldfd);
int dup2(int odlfd,int newfd);
  • 函数说明:

    • dup() 用来复制参数 oldfd 所指的文件描述符,并将它返回。此新的文件描述符和参数oldfd指的是同一个文件,共享所有的锁定、读写位置和各项权限或旗标。例如,当利用 lseek() 对某个文件描述符作用时,另一个文件描述词的读写位置也会随着改变。不过,文件描述符之间并不共享 close-on-exec 旗标。  
    • dup2() 用来复制参数 oldfd 所指的文件描述符,并将它拷贝至参数 newfd 后一块返回。若参数 newfd 为一已打开的文件描述词,则 newfd 所指的文件会先被关闭。如若 oldfd 等于 newfd,则dup2 返回 newfd,而不关闭它。dup2() 所复制的文件描述符,与原来的文件描述符共享各种文件状态,详情可参考 dup() 。
  • 参数:
    • oldfd:原先的文件描述符
    • newfd:新的文件描述符  
  • 返回值:当复制成功时,则返回最小及尚未使用的文件描述符。若有错误则返回-1,errno会存放错误代码。
  • 附加说明:
    • dup2() 相当于调用 fcntl(oldfd,F_DUPFD,newfd);请参考 fcntl()  
    • 在进程间通信时可用来改变进程的标准输入和标准输出。

  文件描述符的赋值是文件描述符表结构体成员中指针的复制。

  

  dup2(fd_in, STDIN_FILENO),相当于就是将 fd_in 文件描述符中的指向文件表项的指针赋值给 STDIN_FILENO 中的指向标准输入的指针,此时,STDIN_FILENO 中的指针指向了fd_in 中的指针指向的文件表项(地址一样了),最终指向了读取的文件。

  则此时 dup1 中 STDIN_FILENO 不再是从标准输入读取,而是从 fd_in 中去读取。这种就是重定向

5.1.3 实例

  将+ 和 - 改为输入输出重定向

  mcat.c

 #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "io.h"
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h> /*
* bin/mcat + append.txt(+ 为输入重定向)
* bin/mcat - append.txt(- 为输出重定向)
*/
int main(int argc, const char *argv[])
{
int fd_in;
int fd_out;
int i;
int flag = ; for(i = ; i < argc; i++) {
if(!strcmp("+", argv[i])) {
fd_in = open(argv[++i], O_RDONLY);
if(fd_in < ) {
perror("open error");
exit();
} //将标准输入重定向到文件
if(dup2(fd_in, STDIN_FILENO) != STDIN_FILENO) {
perror("dup2 error");
exit();
} close(fd_in);
} else if(!strcmp("-", argv[i])) {
fd_out = open(argv[++i], O_WRONLY | O_CREAT | O_TRUNC, );
if(fd_out < ) {
perror("open error");
exit();
} //将标准输出重定向到文件
if(dup2(fd_out, STDOUT_FILENO) != STDOUT_FILENO) {
perror("dup2 error");
exit();
} close(fd_out); } else {
flag = ;
fd_in = open(argv[i], O_RDONLY);
if(fd_in < ) {
perror("open error");
exit();
} if(dup2(fd_in, STDIN_FILENO) != STDIN_FILENO) {
perror("dup2 error");
exit();
} copy(STDIN_FILENO, STDOUT_FILENO);
close(fd_in);
}
} if(!flag) {
copy(STDIN_FILENO, STDOUT_FILENO);
} return ;
}

  编译调试如下:

  

五、文件IO——dup 函数的更多相关文章

  1. 六、文件IO——fcntl 函数 和 ioctl 函数

    6.1 fcntl 函数 6.1.1 函数介绍 #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd ...

  2. Linux文件IO操作函数概述

    文件概述 Linux中,一切皆文件.文件为操作系统服务和设备提供了一个简单而一致的接口.这意味着程序完全可以像使用文件那样使用磁盘文件.串行口.打印机和其他设备. 也就是说,大多数情况下,你只需要使用 ...

  3. C标准库函数--文件IO操作函数。

    C标准库文件读写函数总结:都是对文件流进行输入输出的函数分为对文件的有格式读写以及无格式读写 一.文件的无格式读写根据每次读写字符的数量,分为三类:1.按字符读写文件 按字符读有三个函数:以下三个函数 ...

  4. 文件IO和标准IO

    2015.2.26 星期四,阴天 今天的内容主要是文件IO man 手册的分册: man -f open 查看那些分册中有openman 1 -- 普通的命令程序man 2 -- 系统调用man 3 ...

  5. 第八篇:文件共享和使用 dup 函数创建新描述符的区别

    前言 文件共享是指同时打开一个文件 用 dup 函数能对指定文件描述符再创建一个新的描述符,且这个新的描述符和旧的描述符指向的是同一个文件. 这两种行为有什么区别呢?下面给出的两张文件系统的图形象的解 ...

  6. 初级文件IO——IO过程、open、close、write、read、lseek、dup、dup2、errno、perror

    先要回答的问题 文件IO指的是什么? 本文主要讲述如何调用Linux OS所提供的相关的OS API,实现文件的读写. 如何理解文件IO? IO就是input output的意思,文件io就是文件输入 ...

  7. 【Linux 应用编程】文件IO操作 - 常用函数

    Linux 系统中的各种输入输出,设计为"一切皆文件".各种各样的IO统一用文件形式访问. 文件类型及基本操作 Linux 系统的大部分系统资源都以文件形式提供给用户读写.这些文件 ...

  8. 文件IO函数和标准IO库的区别

    摘自 http://blog.chinaunix.net/uid-26565142-id-3051729.html 1,文件IO函数,在Unix中,有如下5个:open,read,write,lsee ...

  9. (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

随机推荐

  1. [JSOI2008]魔兽地图(树形dp)

    DotR (Defense of the Robots) Allstars是一个风靡全球的魔兽地图,他的规则简单与同样流行的地图DotA (Defense of the Ancients) Allst ...

  2. mysql 单表卡死

    由于单表数据量过大导致的更新操作处于卡死状态,无法打开也无法修改. 此时需要命令行模式连接数据库,注意点:此处连接需要相同的账号 1. $ SHOW PROCESSLIST; 2. $ kill 37 ...

  3. Hyper-V

    docker与vm同时安装,会导致虚拟机无法启动及网络不通等问题,解决方法分为两步. 1.在网络连接中禁用vEthernet连接. 2.控制面板>程序>程序和功能中 >启用或关闭wi ...

  4. MOSFET的半桥驱动电路设计要领详解

    1 引言 MOSFET凭开关速度快.导通电阻低等优点在开关电源及电机驱动等应用中得到了广泛应用.要想使MOSFET在应用中充分发挥其性能,就必须设计一个适合应用的最优驱动电路和参数.在应用中MOSFE ...

  5. 普及一个Linux的小技能~Ctrl+Z切换到后台运行

    逆天Linux一直是自己摸索的,几年下来也小有心得,前不久PC也换成Ubuntu了,但毕竟不是专门搞运维的,有些知识还是有死角 这不,今天发现了个小技巧,来和大家分享一下: 比如运行一个交互式的程序: ...

  6. C# Winform ListView控件

    一.ListView: 1.视图改为为Detalis: 2.编辑列,每添加一个添加一列,右侧属性Text改列名,停靠位置,列头的长度等等: 3.右侧属性,点开Iteme,添加ListViewItem集 ...

  7. 洛谷P1072 Hankson的趣味题

    这是个NOIP原题... 题意: 给定 a b c d 求 gcd(a, x) = b && lcm(c, x) = d 的x的个数. 可以发现一个朴素算法是从b到d枚举,期望得分50 ...

  8. A1121. Damn Single

    "Damn Single (单身狗)" is the Chinese nickname for someone who is being single. You are suppo ...

  9. 【洛谷P3810】陌上花开

    题目大意:给定一个三维空间点的坐标,求对于任意一个点三维均小于等于这个点的点个数. 题解:学会了简单的 cdq 分治. 首先,先将第一维从小到大排序,再用类似归并排序的操作对第二维进行排序,在第二维合 ...

  10. python面向对象编程 -- 基本概念

    面向对象的编程简要概括就是将要处理的问题抽象为数据和操作的集合,用类对其进行封装.其中数据和操作都称为类的属性,它们是一般是不变的. 对类进行实例化生成我们所说的对象,对象有自己的属性.对象的属性一般 ...