Linux系统编程:dup2()重定向
对于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()重定向的更多相关文章
- linux系统编程(一)概述
glibc库封装了linux系统调用,并提供c语言接口 所以学习linux系统编程,主要参考glibc库系统调用相关api 一.进程控制: fork 创建一个新进程 clone 按指定条件创建子进程 ...
- linux系统编程之文件与io(五)
上一节中已经学习了文件描述符的复制,复制方法有三种,其中最后一种fcntl还并未使用到,关于这个函数,不光只有复制文件描述符的功能,还有其它一些用法,本节就对其进行一一剖析: fcntl常用操作: 这 ...
- Linux 系统编程 学习:03-进程间通信1:Unix IPC(2)信号
Linux 系统编程 学习:03-进程间通信1:Unix IPC(2)信号 背景 上一讲我们介绍了Unix IPC中的2种管道. 回顾一下上一讲的介绍,IPC的方式通常有: Unix IPC包括:管道 ...
- Linux系统编程温故知新系列 --- 01
1.大端法与小端法 大端法:按照从最高有效字节到最低有效字节的顺序存储,称为大端法 小端法:按照从最低有效字节到最高有效字节的顺序存储,称为小端法 网际协议使用大端字节序来传送TCP分节中的多字节整数 ...
- linux系统编程之错误处理
在linux系统编程中,当系统调用出现错误时,有一个整型变量会被设置,这个整型变量就是errno,这个变量的定义在/usr/include/errno.h文件中 #ifndef _ERRNO_H /* ...
- LINUX系统编程 由REDIS的持久化机制联想到的子进程退出的相关问题
19:22:01 2014-08-27 引言: 以前对wait waitpid 以及exit这几个函数只是大致上了解,但是看REDIS的AOF和RDB 2种持久化时 均要处理子进程运行完成退出和父进程 ...
- Linux系统编程-setitimer函数
功能:linux系统编程中,setitimer是一个经常被使用的函数,可用来实现延时和定时的功能. 头文件:sys/time.h 函数原型: int setitimer(int which, cons ...
- Linux系统编程@进程通信(一)
进程间通信概述 需要进程通信的原因: 数据传输 资源共享 通知事件 进程控制 Linux进程间通信(IPC)发展由来 Unix进程间通信 基于System V进程间通信(System V:UNIX系统 ...
- Linux 系统编程
简介和主要概念 Linux 系统编程最突出的特点是要求系统程序员对它们工作的的系统的硬件和操作系统有深入和全面的了解,当然它们还有库和系统调用上的区别. 系统编程分为:驱动编程.用户空间编程和网络编程 ...
- Linux C 程序 文件操作(Linux系统编程)(14)
文件操作(Linux系统编程) 创建一个目录时,系统会自动创建两个目录.和.. C语言实现权限控制函数 #include<stdio.h> #include<stdlib.h> ...
随机推荐
- 《高性能 JavaScript》读书笔记(一)
一. 加载和执行——优化JavaScript规则: 1. 将脚本放在底部:2. 减少页面中外链脚本文件的数量: 比如,下载单个100kb的文件将比下载4个25kb的文件更快.这个可以通过离线打包工具或 ...
- debugging python with IDLE
1. start IDLE "Python 2.5"→"IDLE(Python GUI)" 2. open your source file window Fr ...
- Nyoj 网络的可靠性(水题)
描述 A公司是全球依靠的互联网解决方案提供商,也是2010年世博会的高级赞助商.它将提供先进的网络协作技术,展示其”智能+互联“的生活概念,同时为参观者提供高品质的个人体验和互动,以”信息通信,尽情城 ...
- js 正则学习小记之匹配字符串
原文:js 正则学习小记之匹配字符串 今天看了第5章几个例子,有点收获,记录下来当作回顾也当作分享. 关于匹配字符串问题,有很多种类型,今天讨论 js 代码里的字符串匹配.(因为我想学完之后写个语法高 ...
- hdu 5073 Galaxy(2014acm鞍山亚洲分部 D)
主题链接:http://acm.hdu.edu.cn/showproblem.php? pid=5073 Galaxy Time Limit: 2000/1000 MS (Java/Others) ...
- 使用myeclipse将Javaj项目标ar套餐邂逅classnotfound解决问题的方法
做一件事的今天,该Java项目打包成jar文件.折腾2小时,最终运行jar文件报告classnotfound异常,我觉得程序写入依赖jar包不玩成,但是,我手动添加.或不.网上找了很多办法.或不.后. ...
- 开发者:网站 & SDK
{ 收集的一些.开发工具 } Teambition 团队协作工具 GitCafe 代码托管 FIR.im App 托管平台 Coding 代码托管,项目管理,WebIDE 计蒜客 编程学习 SendC ...
- javascript中类的属性研究
原文:javascript中类的属性研究 本篇文章主要针对javascript的属性进行分析,由于javascript是一种基于对象的语言,本身没有类的概念,所以对于javascript的类的定义有很 ...
- 再谈IE的浏览器模式和文档模式
原文:再谈IE的浏览器模式和文档模式 以前在 “IE8兼容视图(IE7 mode)与独立IE7的区别”一文中曾经涉及过浏览器模式和文档模式,但二者的区别却不甚了了,现在有了新的认识,再补充一下. 1. ...
- KnockOut绑定
KnockOut绑定之Click绑定 Click绑定对DOM元素添加一个函数,当DOM元素被点击的时候调用.在button,input 或者a标签中常用,但其实他适用于任何可见的DOM元素. exam ...