Chinaunix首页 | 论坛 | 博客
  • 博客访问: 615015
  • 博文数量: 79
  • 博客积分: 848
  • 博客等级: 军士长
  • 技术积分: 1800
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-26 19:30
文章分类

全部博文(79)

文章存档

2015年(4)

2013年(39)

2012年(36)

分类: C/C++

2012-08-29 11:16:20

我们在编程中常常遇到这样的问题:就是父进程需要截获子进程的输出,进行数据分析或者作为数据返回给socket
通信中的另一端!如何来解决这样的问题呢?这里就用到了进程之间的管道通信和dup2函数!
在介绍dup2函数之前我们先来了解一下!我们先来了解一下什么是管道!
管道是UNIX系统IPC的最古老的方式,并且所有的UNIX和LINUX系统都提供了这样通信方式!
管道是由pipe函数所创建的:
#include
int pipe(int fd[2]);
在这里传递的参数fd[2],实际上是两个文件描述符,其中fd[0]为读而打开的文件描述符,fd[1]为写打开的文件
描述符!当我们在父进程中声明了一个这样的管道,然后执行fork()函数创建出一个子进程时,子进程中就保留了
一个fd[2]的副本,这样我们在子进程中关闭fd[0],在父进程中关闭fd[1],这样就建立一个在父进程和子进程之间
通信的通道,这样从子进程写入信息,就可以从父进程读出来!就如同在父进程和子进程之间建立了一个信息的
通道,我们称之为管道!
熟悉了管道的概念之后,假如我们想要截获子进程的输出,只需要将子进程的标准输出复制给fd[1],这样我们就
可以从父进程中截获子进程的输出了,从而便于我们进行下一步的数据分析,这个复制操作就用到了我们这里提到
的dup2函数!
int dup2(int oldfd,int fd);
dup2 函数跟dup函数相似,但dup2函数允许调用者规定一个有效描述符和目标描述符的id。dup2函数成功返回时,目标描述符(dup2函数的第二个参 数)将变成源描述符(dup2函数的第一个参数)的复制品,换句话说,两个文件描述符现在都指向同一个文件,并且是函数第一个参数指向的文件。
下面来看一个实际的例子:
#include"apue.h"
#include
#include"error.c"
#include
void pr_exit(int status)
{
        if(WIFEXITED(status))
        {
                printf("normal termination, exit status = %d\n",WEXITSTATUS(status));
        }
        else if(WIFSIGNALED(status))
        {
                printf("abnormal termination, signal number = %d%s\n", WTERMSIG(status),
                #ifdef WCOREDUMP
                                 WCOREDUMP(status) ? "(core file generated)" : "");
                #else
                        "");
                #endif
        }
        else if(WIFSTOPPED(status))
        {
                printf("child stopped, signal number = %d\n", WSTOPSIG(status));
        }
}
int main(void)
{
        pid_t pid;
        int status;
        int fd[2];
        int n;
        char line[MAXLINE];
        int s = open("ddx",O_RDWR);
        if(pipe(fd) < 0)
        {
                err_sys("pipe error!");
                exit(0);
        }
        if((pid = fork()) < 0)
  {
                err_sys("fork error!");
        }
        else if(pid == 0)
        {
                close(fd[0]);
                dup2(fd[1],STDOUT_FILENO);//z将标准输出指向了fd[1]!
                if(execl("/home/mini/scripts/sh09.sh","hello","hello",(char*)0) < 0)
                {
                        err_sys("execl error!");
                }
        }
        else
        {
                close(fd[1]);
                n = read(fd[0],line,MAXLINE);
                if(write(s,line,n) < 0)//读取标准输出写入文件!!
                {
                        perror("error:");
                }
                close(s);

        }
        if(waitpid(pid,&status,0) < 0)
    {
                err_sys("waitpid error!");
        }
        pr_exit(status);
        exit(0);
}
本例中我们在父进程中fork()出来一个子进程,并且在子进程中,调用了execl函数执行了一段shell程序,
利用管道和dup2函数截获了子进程的输出,返回给父进程之后,由父进程写入文件!!在这里简单的描述了一下
dup2和管道的用法,以供参考!!
阅读(3574) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~