参考资料:

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[], nbytes;
pid_t childpid;
char string[] = "Hello, world!\n";
char readbuffer[]; pipe(fd); if ((childpid = fork()) == -)
{
perror("fork");
exit();
} if (childpid == )
{
/* Child process closes up input side of pipe */
close( fd[] ); /* Send "string" through the output side of pipe */
write(fd[], string, (strlen(string)+));
exit();
}
else
{
/* Parent process closes up output side of pipe */
close( fd[] ); /* Read in a string from the pipe */
nbytes = read(fd[], readbuffer, sizeof(readbuffer));
if (nbytes != -)
{
printf("Received string: %s", readbuffer);
} } return();
}

下面将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[], nbytes;
pid_t childpid;
char string[] = "Hello, world!\n";
char readbuffer[]; pipe(fd); if ((childpid = fork()) == -)
{
perror("fork");
exit();
} if (childpid == )
{
/* Child process closes up input side of pipe */
close( fd[] ); /* Send "string" through the output side of pipe */
dup2(fd[], STDOUT_FILENO);
//write(fd[1], string, (strlen(string)+1));
printf("hello world\n");
fflush(stdout);
exit();
}
else
{
/* Parent process closes up output side of pipe */
close( fd[] ); /* Read in a string from the pipe */
dup2(fd[], STDIN_FILENO);
//nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
fgets(readbuffer, sizeof(readbuffer), stdin);
if (nbytes != -)
{
printf("from the stdin,Received string: %s", readbuffer);
} } return();
}

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[], nbytes;
pid_t childpid;
char string[] = "Hello, world!\n";
char readbuffer[]; pipe(fd); if ((childpid = fork()) == -)
{
perror("fork");
exit();
} if (childpid == )
{
/* Child process closes up input side of pipe */
close( fd[] ); /* Send "string" through the output side of pipe */
dup2(fd[], STDOUT_FILENO);
execlp( "ls", "ls", "-1", NULL ); exit();
}
else
{
/* Parent process closes up output side of pipe */
close( fd[] ); /* Read in a string from the pipe */
dup2(fd[], STDIN_FILENO);
execlp( "wc", "wc", "-l", NULL ); } return();
}

无名管道跟dup,dup的使用的更多相关文章

  1. linux进程间通信之一:无名管道

    无名管道是linux中管道通信的一种原始方法,有以下特征: 1.单工通信模式,具有固定的读端和写端: 2.管道可以看成是一种特殊的文件,对于它的读写可以使用普通的read(),write()等文件IO ...

  2. Linux 进程通信(无名管道)

    无名管道 无名管道是半双工的,就是对于一个管道来讲,只能读,或者写. 无名管道只能在相关的,有共同祖先的进程间使用(即一般用户父子进程). 一个fork或者execve调用创建的子进程继承了父进程的文 ...

  3. linux进程间通信--无名管道

    管道 只能用于具有亲缘关系的进程之间通信是一个半双工的通信模式, 具有固定的写读端和写端,管道可以看成一种特殊的文件,对它可以使用普通的read.write等操作 管道的创建: #include &l ...

  4. Linux简单程序实例(GNU工具链,进程,线程,无名管道pipe,基于fd的文件操作,信号,scoket)

    一, GNU工具链简介: (1)编译代码步骤: 预处理 -> 编译 -> 汇编 -> 链接: 预处理:去掉注释,进行宏替换,头文件包含等工作: gcc -E test.c -o te ...

  5. linux之无名管道

    1.查看命令: man 2 pipe 2.头文件:#include <unistd.h> 3.函数原型: int pipe(int pipefd[2]); a.pipefd[2] :无名管 ...

  6. UNIX环境高级编程——无名管道和有名管道

    一.进程间通信 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2 ...

  7. 进程间通信IPC之--无名管道(pipe)和有名管道(fifo)(转)

     进程间通信IPC之--无名管道(pipe)和有名管道(fifo) 2012-01-17 22:41:20 分类: C/C++ 每个进程各自有不同的用户地址空间,任何一个进 程的全局变量在另一个进程中 ...

  8. linux无名管道

    特点 无名管道是半双工的,也就是说,一个管道要么只能读,要么只能写 只能在有共同祖先的进程间使用(父子进程.兄弟进程.子孙进程等) fork或者execve调用创建的子进程,继承了父进程的文件描述符 ...

  9. Linux 进程间通信 无名管道(pipe)

    无名管道: 1)只能用于具有亲缘关系的进程之间的通信(无名管道是某一个进程创建的,不像普通文件有路径,在文件系统中是不可见的,其他进程要想打开,只能通过继承的方式去打开) 2)半双工的通信模式,具有固 ...

随机推荐

  1. Linux系统对IO端口和IO内存的管理

    引用:http://blog.csdn.net/ce123_zhouwei/article/details/7204458 一.I/O端口 端口(port)是接口电路中能被CPU直接访问的寄存器的地址 ...

  2. stm32时钟树讲解

    1.管理好时钟,功耗才能更低

  3. canvas绘图详解笔记之线条及线条属性

    创建 canvas 首先创建一个canvas元素,我们只需要在html文件中加入这么一句代码: <canvas id="canvas">当前浏览器不支持canvas,请 ...

  4. 【转】linux之cp/scp命令+scp命令详解

    linux之cp/scp命令+scp命令详解   名称:cp 使用权限:所有使用者 使用方式: cp [options] source dest cp [options] source... dire ...

  5. Python3基础 getatime getctime getmtime 文件的最近访问 + 属性修改 + 内容修改时间

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  6. windows10下cygwin安装神器apt-cyg

    一.背景 需要在cygwin下安装一些库 二.安装 2.1获取apt-cyg源码 git clone https://github.com/transcode-open/apt-cyg.git 2.2 ...

  7. 牌型种数|2015年蓝桥杯B组题解析第七题-fishers

    牌型种数 小明被劫持到X赌城,被迫与其他3人玩牌. 一副扑克牌(去掉大小王牌,共52张),均匀发给4个人,每个人13张. 这时,小明脑子里突然冒出一个问题: 如果不考虑花色,只考虑点数,也不考虑自己得 ...

  8. spring注解注入properties配置文件

    早期,如果需要通过spring读取properties文件中的配置信息,都需要在XML文件中配置文件读取方式. 基于XML的读取方式: <bean class="org.springf ...

  9. BZOJ5293: [Bjoi2018]求和 树上差分

    Description master 对树上的求和非常感兴趣.他生成了一棵有根树,并且希望多次询问这棵树上一段路径上所有节点深度的k  次方和,而且每次的k 可能是不同的.此处节点深度的定义是这个节点 ...

  10. C#学习笔记(六):循环嵌套、复杂数据类型和枚举

    复杂数据类型 默认情况:0,1,2,3 赋值情况:0,3,4,5://修改初始值,后面都会改变 定义在class外面,作用域更大 定义在class里面(类种类),只能在类里使用 枚举作用:方便把不同角 ...