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

文章试读
不拘一个遍程序系列:编程序不能一个脑袋钻到底,有时要学会变通,即所谓的曲线救国。一、二、三、四
职场规划:一些杂七杂八的职场感悟吧。不值钱的软件人才 精力充沛与事业成功   让系分来得更猛烈些吧    不值钱的系统分析师 
我的诗歌:都是我的打油诗,但是很值得一读。不要工作还衣食无忧之四难歌   香格里拉美人图
宝宝图片:超可爱的小宝宝 写博客
考试培训:主要是关于考研、软考和等级的相关题解。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重定向

你可能感兴趣的:(c,unix,C语言编程,Unix编程)