对于Dup2 的理解:

源代码:

 #include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h> #define MSGSIZE 20
#define READ 0
#define WRITE 1 int main(int argc, char const *argv[])
{
int p[], bytes, res, c;
char inbuf[];
int pid;
printf("%c", );
if(pipe(p) == -){// creat the pipe , if pipe is built failed , exit .
perror("pip call");
exit();
}
pid = fork();
if(pid != ){// creat parent pid and child pid.
close(p[READ]);//close parent pipe read
dup2(p[WRITE], );
close(p[WRITE]);//close parent pipe write
execlp(argv[], argv[], NULL);
}
else{ close(p[WRITE]);//close child pipe write dup2(p[READ],); close(p[READ]);//close child pipe read execlp(argv[], argv[], NULL);
}
return ;
}

通过命令行输出:

./a.out “ls” “ps”

仅仅在终端执行了ps的命令, 而没有看到ls 命令的结果。

因此,开始走入了第一个误区:父进程没有执行

通过调试 在父进程执行if条件中加入以下代码:

if(pid != 0){

printf("4556\n");

close(p[READ]);

dup2(p[WRITE], 1);

close(p[WRITE]);

printf("4556\n");

execlp(argv[1], argv[1], NULL);

}

加入了2个printf
, 但是只有dup2 上面的printf
结果输出到屏幕上,因此我注释了 dup2(p[WRITE],
1); 结果在父进程if语句中的dup2
后面的命令都执行并且输出到屏幕上了。通过查找dup2
命令发现了重定向的强大之处。

先解释下
dup2 命令,

int dup2(int filedes, int filedes2);

说明:

用dup2
则可以用filedes2
参数指定新描述符的数值。如果filedes2
已经打开,则先将其关闭。如若filedes
等于filedes2,则返回filedes2,而不关闭它。

dup2(p[WRITE], 1);
这句话可以理解为将标准输出重定向到
p[WRITE], 因此在这句话后面的所有printf
语句打印或者exec
执行的内容都输入到了p[WRITE]中。刚开始有个迷惑,就是既然已经close(1)了,为什么还能输入到p[WRITE]中,通过自己的直觉判断,应当是close(1)关闭了屏幕的输出,但是它有缓冲区保存printf打印出的内容,并且由于重定向的关系,输进了p[WRITE]中。

代码:

 #include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h> #define MSGSIZE 20
#define READ 0
#define WRITE 1 int main(int argc, char const *argv[])
{
int p[], bytes, res, c;
char inbuf[];
int pid;
printf("%c", );
if(pipe(p) == -){// creat the pipe , if pipe is built failed , exit .
perror("pip call");
exit();
}
pid = fork();
if(pid != ){// creat parent pid and child pid.
close(p[READ]);//close parent pipe read
dup2(p[WRITE], );
close(p[WRITE]);//close parent pipe write
printf("123!\n");
execlp(argv[], argv[], NULL);
perror("execlp");//error output
}
else{
while(){
res = read(p[READ], inbuf, );
if(res>)
printf("%s\n", inbuf);
break;
} close(p[WRITE]);//close child pipe write dup2(p[READ],); close(p[READ]);//close child pipe read execlp(argv[], argv[], NULL);
}
return ;
}

通过在子进程中用while(1)循环读取p[READ]内容,发现读出了父进程本应在屏幕上打印的内容,因此父进程是执行了所有命令行,只是通过重定向命令存到了p[WRITE]管道中。

由于有dup2(p[READ], 0) 命令,因此猜测标准输入的文件描述符定向到了p[READ] , 因此如果猜测没错,通过getchar()读取文件标准输入并把P[READ]的内容输出到屏幕上则证明我猜想没错。

代码:

 #include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h> #define MSGSIZE 20
#define READ 0
#define WRITE 1 int main(int argc, char const *argv[])
{
int p[], bytes, res, c;
char inbuf[];
int pid;
printf("%c", );
if(pipe(p) == -){// creat the pipe , if pipe is built failed , exit .
perror("pip call");
exit();
}
pid = fork();
if(pid != ){// creat parent pid and child pid.
close(p[READ]);//close parent pipe read
dup2(p[WRITE], );
close(p[WRITE]);//close parent pipe write
printf("123!\n");
execlp(argv[], argv[], NULL);
perror("execlp");//error output
}
else{
// while(1){
// res = read(p[READ], inbuf, 10240);
// if(res>0)
// printf("%s\n", inbuf);
// break;
// } close(p[WRITE]);//close child pipe write dup2(p[READ],);
while((c=getchar()) != -){
printf("%c", c);
}
close(p[READ]);//close child pipe read execlp(argv[], argv[], NULL);
}
return ;
}

通过在dup2(p[READ],
0) 后面while循环读入输入流输入的字符并且打印出来,
发现结果果然是p[READ]的内容,猜疑没错。

为了更清楚的理解dup2的重定向含义,想理解dup2(fd,0)和dup2(0,fd)功能相同吗?

为了得到答案,找些资料发现,答案是不同。

测试代码:

 #include <stdio.h>
#include <unistd.h>
#include <fcntl.h> #define BUFMAXSIZE 4096 int main(int argc, char *argv[])
{
int fd;
int n;
char buf[BUFMAXSIZE];
int fs;
fs = open("test", O_RDWR);
if((fd = open("duan", O_RDWR )) == -)
{
perror("open error!");
return();
} dup2(fd, ); // dup2(0,fd); while((n = read(fs, buf, BUFMAXSIZE)) > )
{
printf("begin to read...\n");
if(write(STDOUT_FILENO, buf, n) != n)
{
perror("write error!");
return();
}
printf("end to write...\n");
}
if(n < )
{
perror("read error");
return();
} return ;
}

dup(fd, 0) 这段代码测试, 打印出了 duan 文件里面的内容。

之后创建个文件 Levi 里面写和duan 文件不同的内容。

通过./a. out < Levi输出:

第一个输出是 dup(fd, 0) 输出了Duan 文件的内容。即是fd的内容

第二个输出是 dup(0, fd) 输出了 Levi 文件的内容。即是 通过文件重定向到标准输入的内容。

从图中的输出结果已经可以看到两者的区别了。

第一种dup2(fd,0)之前已经将 fd 初始化指向到文本 Duan了,

并且不会被后面的代码所修改。

第二种dup2(0,fd)则将 fd 重新指向到文件描述符0所代表的文件(即终端标准输入)了。

那么可以看到,程序的执行中不会再读取 Duan 文件了。

而是进入了一种交互模式。

另外,这时“输入重定向”也可以生效了。

文件描述符0被 “<” 重定向到 Duan 了

所以,这里直接输出了该文本的内容。

dup2(fd,0) 相当于“输入重定向”的功能,

dup2(0,fd) 不是表示 fd 所指的文件接收来自终端的输入,因为,fd 已经不再指向原来的那个文件了。

它和文件描述符0 已经在共享同一个文件表项(即指向终端标准输入的那个表项)了。

“输出重定向”的功能可以用 dup2(fd ,1) 替代。

dup2(fd,1) 和 dup2(1,fd) 也是大同小异。

Linux系统编程:dup2()重定向的更多相关文章

  1. linux系统编程(一)概述

    glibc库封装了linux系统调用,并提供c语言接口 所以学习linux系统编程,主要参考glibc库系统调用相关api 一.进程控制: fork 创建一个新进程 clone 按指定条件创建子进程 ...

  2. linux系统编程之文件与io(五)

    上一节中已经学习了文件描述符的复制,复制方法有三种,其中最后一种fcntl还并未使用到,关于这个函数,不光只有复制文件描述符的功能,还有其它一些用法,本节就对其进行一一剖析: fcntl常用操作: 这 ...

  3. Linux 系统编程 学习:03-进程间通信1:Unix IPC(2)信号

    Linux 系统编程 学习:03-进程间通信1:Unix IPC(2)信号 背景 上一讲我们介绍了Unix IPC中的2种管道. 回顾一下上一讲的介绍,IPC的方式通常有: Unix IPC包括:管道 ...

  4. Linux系统编程温故知新系列 --- 01

    1.大端法与小端法 大端法:按照从最高有效字节到最低有效字节的顺序存储,称为大端法 小端法:按照从最低有效字节到最高有效字节的顺序存储,称为小端法 网际协议使用大端字节序来传送TCP分节中的多字节整数 ...

  5. linux系统编程之错误处理

    在linux系统编程中,当系统调用出现错误时,有一个整型变量会被设置,这个整型变量就是errno,这个变量的定义在/usr/include/errno.h文件中 #ifndef _ERRNO_H /* ...

  6. LINUX系统编程 由REDIS的持久化机制联想到的子进程退出的相关问题

    19:22:01 2014-08-27 引言: 以前对wait waitpid 以及exit这几个函数只是大致上了解,但是看REDIS的AOF和RDB 2种持久化时 均要处理子进程运行完成退出和父进程 ...

  7. Linux系统编程-setitimer函数

    功能:linux系统编程中,setitimer是一个经常被使用的函数,可用来实现延时和定时的功能. 头文件:sys/time.h 函数原型: int setitimer(int which, cons ...

  8. Linux系统编程@进程通信(一)

    进程间通信概述 需要进程通信的原因: 数据传输 资源共享 通知事件 进程控制 Linux进程间通信(IPC)发展由来 Unix进程间通信 基于System V进程间通信(System V:UNIX系统 ...

  9. Linux 系统编程

    简介和主要概念 Linux 系统编程最突出的特点是要求系统程序员对它们工作的的系统的硬件和操作系统有深入和全面的了解,当然它们还有库和系统调用上的区别. 系统编程分为:驱动编程.用户空间编程和网络编程 ...

  10. Linux C 程序 文件操作(Linux系统编程)(14)

    文件操作(Linux系统编程) 创建一个目录时,系统会自动创建两个目录.和.. C语言实现权限控制函数 #include<stdio.h> #include<stdlib.h> ...

随机推荐

  1. Hbase在的应用经验的统计

    1. 需求统计 互联网上对于数据的统计,一个重要的应用就是对站点站点数据的统计,比如CNZZ站长统计.百度统计.Google Analytics.量子恒道统计等等. 站点站点统计工具无外乎有下面一些功 ...

  2. 于 jsp第横梁list数据

            往往我们都会将查询到的数据显示到界面中,那么该怎样在界面显示.请看以下的具体解释:     0)前提得在jsp页面中获取后台传过来的数据(在此为List集合):             ...

  3. strncpy和strcpy

    实体化代码运行图: 实现代码: #include <stdio.h> #include <string.h> #include <math.h> #include ...

  4. 大数据系列修炼-Scala课程04

    Scala中继承实现:超类的构造.字段重写.方法重写 关于超类的构建:超类可以在子类没有位置的限制,可以在子类中调用父类的方法 类中字段重写:在重写字段前面加一个override就可以重新赋值 类中方 ...

  5. windows已安装solr

    下载地址:http://archive.apache.org/dist/lucene/solr/ 操作环境:  Win7,Tomcat6, Solr4.3, Jdk6 下载solr4.3的包,解压到本 ...

  6. Web字体@font-face对于中文字体的使用

    今天算是刚开始玩博客园..感觉很新鲜在首页 上看到了一个博客http://www.cnblogs.com/liuminghai/p/4238256.html是关于web文字的,挺不错 但是B/S的前端 ...

  7. 小程序大智慧,sqlserver 注释提取工具

    原文:小程序大智慧,sqlserver 注释提取工具 开篇背景 我习惯在写表的创建脚本时将注释直接写在脚本里,比如 /*账套*/ CREATE TABLE [dbo].[AccountingBook] ...

  8. 教你发布Silverlight Bussiness Application(SQL Server 登录,局域网访问,以及使用ArcGIS Server服务需要注意的问题)

    原文:教你发布Silverlight Bussiness Application(SQL Server 登录,局域网访问,以及使用ArcGIS Server服务需要注意的问题) 之前发布过Silver ...

  9. 搭建一个BS 的简单SOA 架构(直接通过jquery 调用后台的 wcf 服务的架构)(第一天)

    亲们!还在用传统的三层架构吗?你还在对SOA架构 不了解吗? 那就赶快来学习下一个 比较简单的SOA的架构吧!我会手把手的 教会你们怎么搭建这个 简单的SOA的架构. 其中用的技术点保证  WCF,a ...

  10. 基于Http替补新闻WebService数据交换

    该系统的工作之间的相互作用.随着信息化建设的发展,而业界SOA了解并带来低TOC(总拥有成本)其他优势.越来越多的高层次的信息使用者关注. 这里暂且不提SOA这种架构规划.在系统间集成协议简单的讨论. ...