文章试读
|
不拘一个遍程序系列:编程序不能一个脑袋钻到底,有时要学会变通,即所谓的曲线救国。一、二、三、四
职场规划:一些杂七杂八的职场感悟吧。不值钱的软件人才 精力充沛与事业成功 让系分来得更猛烈些吧 不值钱的系统分析师
我的诗歌:都是我的打油诗,但是很值得一读。不要工作还衣食无忧之四难歌 香格里拉美人图
宝宝图片:超可爱的小宝宝 写博客
考试培训:主要是关于考研、软考和等级的相关题解。2009考研试题分析 2008年12月程序员试题分析 2009年软考备考全攻略 2008年5月程序员试题解析
|
《精通Unix下C语言编程与项目实践》之七
标准I/O重定向
作者:朱云翔,胡平
11.2.4 连接标准I/O的管道模型
管道在
shell
中最常见的应用是连接不同进程的输入输出,比如使
A
进程的输出变成
B
进程的输入等。考察
shell
命令“
cat pipe3.c | more
”,进程“
more
”使用了进程“
cat pipe3.c
”的输出。
例
1.
分别重定向标准输入、标准输出、标准错误输出到文件描述符
fd1
、
fd2
和
fd3
中。
答:复制文件描述符
fd1
到文件描述符
0
中即可重定向标准输入,其它的类似,如以下语句所示:
dup2(fd1, 0); /*
复制
fd1
到文件描述符
0
中,更改标准输入为
fd1 */
dup2(fd2, 1); /*
复制
fd2
到文件描述符
1
中,更改标准输出为
fd2 */
dup2(fd3, 2); /*
复制
fd3
到文件描述符
2
中,更改标准错误输出为
fd3 */
当执行“
dup2(fd1, 0)
”后,文件描述符
0
就对应到了
fd1
所对应的文件中,而一些标准输出函数,如
printf
、
puts
等仍然向描述符
0
中写入内容,从而达到了重定向的效果。
模型
使用管道将父进程标准输入连接到子进程标准输入的方法如下:
(1)
创建管道,返回无名管道的两个文件描述符
fildes[0]
和
fildes[1]
。
(2)
创建子进程,子进程中继承无名管道文件描述符。
(3)
父进程关闭管道的输出端,即关闭只读文件描述符
fileds[0]
。
(4)
父进程将标准输出(
stdout
,文件描述符
1
)重定向为文件描述符
fileds[1]
。
(5)
子进程关闭管道的输入端,即关闭只写文件描述符
fileds[1]
。
(6)
子进程将标准输入(
stdin
,文件描述符
0
)重定向为文件描述符
fileds[0]
。
最终创建的管道流如图
11-7
所示:
图
11-7
父子进程标准
I/O
管道(父进程流向子进程)
实例
本处设计一个将父进程标准输出流连接到子进程标准输入流的管道,父进程向
stdout
输出的“
Hello!
”直接转移到子进程的
stdin
,由子进程“
gets(buf)
”语句所获取。如代码
11-6
所示:
代码
11-6
父进程的输出连接子进程的输入通信实例(节自
/code/chapter11/pipe3.c
)
#include <unistd.h>
#include <stdio.h>
int main()
{
int fildes[2];
pid_t pid;
int i, j;
char buf[256];
if (pipe(fildes) < 0 || (pid = fork()) < 0) /*
创建管道和子进程
*/
{
fprintf(stderr, "error!\n");
return 1;
}
if (pid == 0)
{
/*
�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D子进程�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D
*/
close(fildes[1]);
dup2(fildes[0], 0); /*
重定向
stdin
到
fildes[0]
中
*/
close(fildes[0]);
gets(buf); /*
读入输入,其实是读取父进程输出
*/
fprintf(stderr, "child:[%s]\n", buf);
return 2;
}
/*
�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D父进程�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D
*/
close(fildes[0]);
dup2(fildes[1], 1); /*
重定向
stdout
到
fildes[1]
中
*/
close(fildes[1]);
puts("Hello!"); /*
输出,同时增加子进程的输入信息
*/
return 0;
}
编译与运行代码
11-6
:
# make pipe3
cc -O -o pipe3 pipe3.c
# ./pipe3
child:[Hello!]
上例中,父进程的标准输出已经重定向到管道中,故父进程
puts
未能将结果打印到屏幕上。
相关文章:
封面 前言 目录 策划 作者
动态库 变长参数 文件锁 外设 僵死进程
定时器 I/O重定向