对于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) 也是大同小异。

最新文章

  1. 图文介绍如何在Eclipse统计代码行数(转)
  2. Objective-C中的集合类
  3. K2新网站(官网和BPM社区)正式上线了
  4. 收缩SQL Server日志不是那么简单的(翻译)
  5. SharePoint 2013 隐藏部分Ribbon菜单
  6. Oracle导入导出dmp文件
  7. js变量申明提前及缺省参数
  8. jquery validate 配合ligerui使用
  9. HDU 5758 Explorer Bo(树形DP)
  10. 《Django By Example》第十二章 中文 翻译 (个人学习,渣翻)
  11. java从命令行接收多个数字,求和程序分析
  12. 接口测试(jmeter和postman 接口使用)
  13. Go语言中的string知识点
  14. 【转】最近很火的 Safe Area 到底是什么
  15. 关于mariad&amp;mysql部分
  16. 自定义滤镜 ColorMatrixFilter
  17. ubuntu部署git
  18. Java如何中断正在运行的线程?
  19. 如何在&lt;textarea&gt;标签中使用并解析HTML标签
  20. c++标准库中的string常用函数总结《转》

热门文章

  1. Android fragment onActivityResult 不起作用
  2. 第18章 备忘录模式(Memento Pattern)
  3. myql_链接丢失异常_mybaits _等框架_报错_The last packet successfully
  4. Linux查看非root流程执行
  5. Android中适用于ListView、GridView等组件的通用Adapter
  6. C语言星号的秘密
  7. SpringMVC一路总结(
  8. lua for通过循环table一些差异
  9. Excel 创建31 个 工作表
  10. java ResultSet 结果集处理 createStatement() 里参数的意义(第一弹)