精通Unix下C语言编程与项目实践》之七——标准I/O重定向

简介:
《精通Unix下C语言编程与项目实践》之七
标准I/O重定向 
作者:朱云翔,胡平

11.2.4 连接标准I/O的管道模型

管道在shell中最常见的应用是连接不同进程的输入输出,比如使A进程的输出变成B进程的输入等。考察shell命令“cat pipe3.c | more”,进程“more”使用了进程“cat pipe3.c”的输出。
1. 分别重定向标准输入、标准输出、标准错误输出到文件描述符fd1fd2fd3中。
答:复制文件描述符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所对应的文件中,而一些标准输出函数,如printfputs等仍然向描述符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)
    {
    /* ―――――――――――――――――子进程―――――――――――――――――― */
        close(fildes[1]);                  
        dup2(fildes[0], 0);                 /* 重定向stdinfildes[0] */
        close(fildes[0]);
        gets(buf);                          /* 读入输入,其实是读取父进程输出 */
        fprintf(stderr, "child:[%s]\n", buf);
        return 2;
    }
    /* ―――――――――――――――――父进程―――――――――――――――――― */
    close(fildes[0]);
    dup2(fildes[1], 1);                     /* 重定向stdoutfildes[1] */
    close(fildes[1]);
    puts("Hello!");                         /* 输出,同时增加子进程的输入信息*/
    return 0;                          
}
编译与运行代码11-6
# make pipe3
        cc -O -o pipe3 pipe3.c
# ./pipe3
child:[Hello!]
上例中,父进程的标准输出已经重定向到管道中,故父进程puts未能将结果打印到屏幕上



 本文转自 zhuyunxiang 51CTO博客,原文链接:http://blog.51cto.com/zhuyunxiang/134458,如需转载请自行联系原作者


相关文章
|
22天前
|
存储 Java C语言
【C语言入门】初识C语言:掌握编程的基石
【C语言入门】初识C语言:掌握编程的基石
28 4
【C语言入门】初识C语言:掌握编程的基石
|
22天前
|
存储 Java 程序员
【C语言入门】C语言入门:探索编程世界的基础概念
【C语言入门】C语言入门:探索编程世界的基础概念
26 2
|
1月前
|
C语言
【海贼王编程冒险 - C语言海上篇】库函数怎样模拟实现?
【海贼王编程冒险 - C语言海上篇】库函数怎样模拟实现?
17 1
|
21天前
|
存储 算法 程序员
C语言编程—递归
递归是函数自我调用的编程技术,常用于解决分治问题,如计算阶乘和斐波那契数列。示例中展示了C语言的阶乘和斐波那契数列递归实现。递归需满足:问题可转化为规模更小的同类问题,存在结束条件以防止无限循环,并可能消耗大量时间和栈空间。栈用于存储函数调用信息,过多递归可能导致栈溢出。递归虽简洁,但非最优效率选择,递推算法通常是更好的替代方案。
26 0
|
22天前
|
Linux C语言
【编程小实验】C语言实现:无限循环写入文本文件,支持Ctrl+C中断与数据追加(附完整源码)
在Linux中,文件I/O(输入/输出)是程序与文件进行交互的基本方式,包括读取文件内容和向文件写入数据。这通常通过标准的C库函数来实现,下面是一些基本的文件读写操作和代码示例。
|
23天前
|
编译器 C语言
C语言编程语法—结构
C语言基础概要:令牌包括关键字、标识符、常量、字符串和符号,如`printf(&quot;Hello,World!\n&quot;);`含5个令牌。分号是语句结束符,注释用`/*...*/`包围。标识符是变量等的名称,以字母、下划线开头,后跟字母、数字。C语言有32个关键字,如`int`,空格用于分隔语句元素,提升可读性。
14 0
|
1月前
|
编译器 C语言 C++
【海贼王编程冒险 - C语言海上篇】自定义类型:结构体,枚举,联合怎样定义?如何使用?
【海贼王编程冒险 - C语言海上篇】自定义类型:结构体,枚举,联合怎样定义?如何使用?
13 0
|
2月前
|
缓存 网络协议 Unix
Linux(UNIX)五种网络I/O模型与IO多路复用
Linux(UNIX)五种网络I/O模型与IO多路复用
134 0
|
2月前
|
Unix Shell Linux
在Unix/Linux操作系统中,Shell脚本广泛用于自动化任务
在Unix/Linux操作系统中,Shell脚本广泛用于自动化任务
49 2