zoukankan      html  css  js  c++  java
  • 无名管道跟dup,dup的使用

    参考资料:

    http://www.tldp.org/LDP/lpg/node11.html

    http://blog.csdn.net/yeyuangen/article/details/6852682

    http://blog.sina.com.cn/s/blog_65c5c5990100mx6d.html

    管道是Linux中很重要的一种通信方式,是把一个程序的输出直接连接到另一个程序的输入,常说的管道多是指无名管道,无名管道只能用于具有亲缘关系的进程之间,这是它与有名管道的最大区别。

    下面是一个最简单的匿名管道的例子。

    子进程中,先关闭管道的读出端,然后在管道的写端写入数据

    在父进程中,先关闭管道的写入端,然后在管道的读出端读出数据。

    int pipe( int fd[2] ); 
    NOTES: fd[0] is set up for reading, fd[1] is set up for writing
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(void)
    {
        int     fd[2], nbytes;
        pid_t   childpid;
        char    string[] = "Hello, world!
    ";
        char    readbuffer[80];
    
        pipe(fd);
        
        if ((childpid = fork()) == -1)
        {
            perror("fork");
            exit(1);
        }
    
        if (childpid == 0)
        {
            /* Child process closes up input side of pipe */
            close( fd[0] );
    
            /* Send "string" through the output side of pipe */
            write(fd[1], string, (strlen(string)+1));
            exit(0);
        }
        else
        {
            /* Parent process closes up output side of pipe */
            close( fd[1] );
    
            /* Read in a string from the pipe */
            nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
            if (nbytes != -1)
            {
                printf("Received string: %s", readbuffer);
            }
                
        }
            
            return(0);
    }

     下面将dup跟管道结合其来使用。

    在子进程中调用  dup2(fd[1], STDOUT_FILENO); 则printf("hello world ");的数据就会写入到fd[1]中

    在父进程中调用 dup2(fd[0], STDIN_FILENO); 则fgets(readbuffer, sizeof(readbuffer), stdin);会把fd[0]的数据读取出来。

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(void)
    {
        int     fd[2], nbytes;
        pid_t   childpid;
        char    string[] = "Hello, world!
    ";
        char    readbuffer[80];
    
        pipe(fd);
        
        if ((childpid = fork()) == -1)
        {
            perror("fork");
            exit(1);
        }
    
        if (childpid == 0)
        {
            /* Child process closes up input side of pipe */
            close( fd[0] );
    
            /* Send "string" through the output side of pipe */
            dup2(fd[1], STDOUT_FILENO);
            //write(fd[1], string, (strlen(string)+1));
            printf("hello world
    ");
            fflush(stdout);
            exit(0);
        }
        else
        {
            /* Parent process closes up output side of pipe */
            close( fd[1] );
    
            /* Read in a string from the pipe */
            dup2(fd[0], STDIN_FILENO);
            //nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
            fgets(readbuffer, sizeof(readbuffer), stdin);
            if (nbytes != -1)
            {
                printf("from the stdin,Received string: %s", readbuffer);
            }
                
        }
            
            return(0);
    }

    Often, the descriptors in the child are duplicated onto standard input or output. The child can then exec() another program, which inherits the standard streams. Let's look at the dup2() system call:

    我们的子进程把它的输出重定向的管道的写端,然后,父进程将它的输入重定向到管道的读端

    子进程关闭 管道读端  close( fd[0] );  调用  dup2(fd[1], STDOUT_FILENO);  将管道的写端重定向到标准输出

    父进程关闭 管道写端 close( fd[1] );   调用  dup2(fd[0], STDIN_FILENO);    将管道的读端重定向到标准输入

    The child can then exec() another program, which inherits the standard streams.

    工作流程:

    子进程调用  execlp( "ls", "ls", "-1", NULL );  ----> 标准输出----->管道的写端------->

    管道的读端(父进程)------->标准输入---->execlp( "wc", "wc", "-l", NULL );

    我们看到的结果是  ls -1|wc -l 的结果

    管道命令的使用  :

    第一条命令 | 第二条命令

    将第一条命令的结果作为第二条命令的参数来使用

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(void)
    {
        int     fd[2], nbytes;
        pid_t   childpid;
        char    string[] = "Hello, world!
    ";
        char    readbuffer[80];
    
        pipe(fd);
        
        if ((childpid = fork()) == -1)
        {
            perror("fork");
            exit(1);
        }
    
        if (childpid == 0)
        {
            /* Child process closes up input side of pipe */
            close( fd[0] );
    
            /* Send "string" through the output side of pipe */
            dup2(fd[1], STDOUT_FILENO);
            execlp( "ls", "ls", "-1", NULL );
     
            exit(0);
        }
        else
        {
            /* Parent process closes up output side of pipe */
            close( fd[1] );
    
            /* Read in a string from the pipe */
            dup2(fd[0], STDIN_FILENO);
            execlp( "wc", "wc", "-l", NULL );
                
        }
            
        return(0);
    }
  • 相关阅读:
    [Zjoi2014]力(FFT,卷积)
    LOJ 6240. 仙人掌
    Web 服务编程技巧和诀窍: 将 <xsd:any/> 元素用于自定义序列化(转)
    Ant工具使用说明(转)
    Web 服务编程技巧与窍门: 用 SAAJ 和 JAXRPC 构建 SOAP 响应信封(转)
    Axis2 quick start 中文版
    使用SOAP开发java web服务Axis开发方案(转)
    k 动画脚本很有算法 同时可以借鉴这里的画圆
    ui 界面美观化 (多维子材质脚本)
    系类函数介绍 之中可能没有一些预订变量 应用时要自己加上。
  • 原文地址:https://www.cnblogs.com/zhangxuan/p/6274107.html
Copyright © 2011-2022 走看看