连接标准I/O的管道模型
来源:互联网 发布:淘宝拍照用哪款相机好 编辑:程序博客网 时间:2024/06/04 20:43
管道在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
#include
int main()
{
int fildes[2];
pid_t pid;
int i, j;
char buf[256];
if (pipe(fildes) /* 创建管道和子进程 */
{
fprintf(stderr, "error!\n");
return 1;
}
if (pid == 0)
{
/* ―――――――――――――――――子进程―――――――――――――――――― */
close(fildes[1]);
dup2(fildes[0], 0); /* 重定向stdin到fildes[0]中 */
close(fildes[0]);
gets(buf); /* 读入输入,其实是读取父进程输出 */
fprintf(stderr, "child:[%s]\n", buf);
return 2;
}
/* ―――――――――――――――――父进程―――――――――――――――――― */
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未能将结果打印到屏幕上。
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/95011/showart_1913104.html
例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
#include
int main()
{
int fildes[2];
pid_t pid;
int i, j;
char buf[256];
if (pipe(fildes) /* 创建管道和子进程 */
{
fprintf(stderr, "error!\n");
return 1;
}
if (pid == 0)
{
/* ―――――――――――――――――子进程―――――――――――――――――― */
close(fildes[1]);
dup2(fildes[0], 0); /* 重定向stdin到fildes[0]中 */
close(fildes[0]);
gets(buf); /* 读入输入,其实是读取父进程输出 */
fprintf(stderr, "child:[%s]\n", buf);
return 2;
}
/* ―――――――――――――――――父进程―――――――――――――――――― */
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未能将结果打印到屏幕上。
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/95011/showart_1913104.html
- 连接标准I/O的管道模型
- 标准I/O和管道
- Windows 命名管道 + 异步I/O模型
- Windows 命名管道 + 异步I/O模型
- Linux 管道的I/O
- 标准的I/O函数
- 标准的I/O流
- 标准I/O的机理
- 使用简单的管道I/O
- socket的I/O模型
- I/O模型的区别
- LINUX的I/O模型
- 标准I/O文件I/O的区别
- 文件I/O和标准I/O的使用
- 文件I/O和标准I/O的区别
- 文件I/O和标准I/O的区别
- 文件I/O和标准I/O的区别
- 文件I/O和标准I/O的区别
- Apache 中使用的 APR Memory Pool 分析
- 如何编写linux下nand flash驱动(转)
- start with ... CONNECT BY PRIOR
- 嵌入式Linux学习漫谈之Linux系统 [转自crosstar嵌入式学院]
- Windows环境下Unicode编程总结和将ANSI转换到Unicode 将Unicode转换到ANSI
- 连接标准I/O的管道模型
- Unicode(UTF16)文件读写终极方案---用C++标准的字节流读取,转化为宽字符(wchar_t),再以字节流写入
- linux下C语言socket网络编程简例
- OSGI笔记(一)
- Tsung的源码 学习
- STUN协议检测网络环境流程
- 读书必须有方法
- poj1258 - Agri-Net
- Bos平台修改发布业务单元的jdk版本