无名管道跟dup,dup的使用

本文详细介绍了Linux中的管道通信机制,包括无名管道的基本概念、工作原理及其应用实例。通过两个进程间的通信示例,展示了如何利用管道进行数据传递,并结合dup2与exec函数实现了复杂的命令级联操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考资料:

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

http://blog.youkuaiyun.com/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!\n";
    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\n");的数据就会写入到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!\n";
    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\n");
        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!\n";
    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);
}

 

转载于:https://www.cnblogs.com/zhangxuan/p/6274107.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值