一,什么是管道

管道是Linux支持的最初Unix IPC形式之一,具有以下特点:

  • 管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;
  • 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);
  • 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中。
  • 数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。

管道的实现机制:

管道是由内核管理的一个缓冲区,相当于我们放入内存中的一个纸条。管道的一端连接一个进程的输出。这个进程会向管道中放入信息。管道的另一端连接一个进程的输入,这个进程取出被放入管道的信息。一个缓冲区不需要很大,它被设计成为环形的数据结构,以便管道可以被循环利用。当管道中没有信息的话,从管道中读取的进程会等待,直到另一端的进程放入信息。当管道被放满信息的时候,尝试放入信息的进程会等待,直到另一端的进程取出信息。当两个进程都终结的时候,管道也自动消失。

二,管道的创建(pipe)

包含头文件<unistd.h>

功能:创建一无名管道

原型:

int pipe(int fd[2]);

参数:

fd:文件描述符数组,其中fd[0]表示读端, fd[1]表示写端

返回值:成功返回0,失败返回错误代码

man帮助说明:

DESCRIPTION

       pipe() creates a pipe, a unidirectional data channel that can be used
for interprocess communication. The array pipefd is used to return
two file descriptors referring to the ends of the pipe. pipefd[0]
refers to the read end of the pipe. pipefd[1] refers to the write
end of the pipe. Data written to the write end of the pipe is
buffered by the kernel until it is read from the read end of the
pipe. For further details, see pipe(7).
 
该函数创建的管道的两端处于一个进程中间,在实际应 用中没有太大意义,因此,一个进程在由pipe()创建管道后,一般再fork一个子进程,然后通过管道实现父子进程间的通信(因此也不难推出,只要两个 进程中存在亲缘关系,这里的亲缘关系指的是具有共同的祖先,都可以采用管道方式来进行通信)。父子进程间具有相同的文件描述符,且指向同一个管道pipe,其他没有关系的进程不能获得pipe()产生的两个文件描述符,也就不能利用同一个管道进行通信。
创建管道后示意图:
 
三,利用管道进行父子进程间数据传输
示例一:子进程向管道中写数据,父进程从管道中读出数据
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h> int main(void)
{
int fds[2];
if(pipe(fds) == -1){
perror("pipe error");
exit(EXIT_FAILURE);
}
pid_t pid;
pid = fork();
if(pid == -1){
perror("fork error");
exit(EXIT_FAILURE);
}
if(pid == 0){
close(fds[0]);//子进程关闭读端
write(fds[1],"hello",5);
exit(EXIT_SUCCESS);
} close(fds[1]);//父进程关闭写端
char buf[10] = {0};
read(fds[0],buf,10);
printf("receive datas = %s\n",buf);
return 0;
}

结果:

示例二:利用管道实现ls |wc –w功能

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h> int main(void)
{
int fds[2];
if(pipe(fds) == -1){
perror("pipe error");
exit(EXIT_FAILURE);
}
pid_t pid;
pid = fork();
if(pid == -1){
perror("fork error");
exit(EXIT_FAILURE);
}
if(pid == 0){ dup2(fds[1],STDOUT_FILENO);//复制文件描述符且指定新复制的fd为标准输出
close(fds[0]);//子进程关闭读端
close(fds[1]);
execlp("ls","ls",NULL);
fprintf(stderr,"exec error\n");
exit(EXIT_FAILURE);
} dup2(fds[0],STDIN_FILENO);
close(fds[1]);//父进程关闭写端
close(fds[0]);
execlp("wc","wc","-w",NULL);
fprintf(stderr, "error execute wc\n");
exit(EXIT_FAILURE);
}

结果:

linux系统编程之管道(一):匿名管道(pipe)的更多相关文章

  1. Linux系统编程之匿名管道

    1.进程间通信介绍 1.1 进程通信的基本概念 在之前我们已经学习过进程地址空间.Linux 环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间.任何一个进程的全局变量在另一个进程中都看不 ...

  2. linux系统编程之管道(三)

    今天继续研究管道的内容,这次主要是研究一下命名管道,以及与之前学过的匿名管道的区别,话不多说,进入正题: 所以说,我们要知道命名管道的作用,可以进行毫无关系的两个进程间进行通讯,这是匿名管道所无法实现 ...

  3. Linux 系统编程 学习:02-进程间通信1:Unix IPC(1)管道

    Linux 系统编程 学习:02-进程间通信1:Unix IPC(1)管道 背景 上一讲我们介绍了创建子进程的方式.我们都知道,创建子进程是为了与父进程协作(或者是为了执行新的程序,参考 Linux ...

  4. Linux 系统编程

    简介和主要概念 Linux 系统编程最突出的特点是要求系统程序员对它们工作的的系统的硬件和操作系统有深入和全面的了解,当然它们还有库和系统调用上的区别. 系统编程分为:驱动编程.用户空间编程和网络编程 ...

  5. 读书笔记之Linux系统编程与深入理解Linux内核

    前言 本人再看深入理解Linux内核的时候发现比较难懂,看了Linux系统编程一说后,觉得Linux系统编程还是简单易懂些,并且两本书都是讲Linux比较底层的东西,只不过侧重点不同,本文就以Linu ...

  6. Linux系统编程@进程通信(一)

    进程间通信概述 需要进程通信的原因: 数据传输 资源共享 通知事件 进程控制 Linux进程间通信(IPC)发展由来 Unix进程间通信 基于System V进程间通信(System V:UNIX系统 ...

  7. linux系统编程之框架

    linux系统编程之框架: 1. 进程 1.1 进程概念 1.1.1 PCB 1.1.2 环境变量 1.2 进程控制 1.3 进程间通信 1.3.1 管道 1.3.2 有名管道 1.3.3 共享内存 ...

  8. linux系统编程(一)概述

    glibc库封装了linux系统调用,并提供c语言接口 所以学习linux系统编程,主要参考glibc库系统调用相关api 一.进程控制: fork 创建一个新进程 clone 按指定条件创建子进程 ...

  9. linux系统编程综合练习-实现一个小型的shell程序(一)

    之前已经花了不少篇幅学习了linux系统编程的很多知识点:文件与io.进程.信号.管道,而零散的知识点,怎么能够综合的串接起来是学习的一个很重要的目的,当然最好的方式就是用所学的知识点做一个项目了,所 ...

  10. Linux 系统编程 学习 总结

    背景 整理了Liunx 关于 进程间通信的 很常见的知识. 目录 与 说明 Linux 系统编程 学习:000-有关概念 介绍了有关的基础概念,为以后的学习打下基础. Linux 系统编程 学习:00 ...

随机推荐

  1. jquery获取input file的文件名,具有兼容性

    var str=$(this).val();var arr=str.split('\\');//注split可以用字符或字符串分割var fileName=arr[arr.length-1];//这就 ...

  2. 第八章 高级搜索树 (xa4)红黑树:删除

  3. tf.cast()

    一.函数 tf.cast() cast( x, dtype, name=None ) 将x的数据格式转化成dtype.例如,原来x的数据格式是bool, 那么将其转化成float以后,就能够将其转化成 ...

  4. CNN、RNN、DNN

    一:神经网络 技术起源于上世纪五.六十年代,当时叫感知机(perceptron),包含有输入层.输出层和一个隐藏层.输入的特征向量通过隐藏层变换到达输出层,由输出层得到分类结果.但早期的单层感知机存在 ...

  5. asp.net 关于Response.Redirect重定向前无法弹出alert对话框的问题

    要实现的功能:某项操作后,使用alert()提示框提示"操作成功"之类的提示,然后使用response.Redirect()来进行页面重定向. 出现的问题:运行代码,操作完成后,直 ...

  6. 解决python中csv文件中文写入问题

    一.前言 一般来说,为了方便,使用python的时候都会使用csv模块去写数据到csv文件,但是写入中文的时候,经常会报错: UnicodeEncodeError: 'ascii' codec can ...

  7. MongoDB的文档、集合、数据库(二)

    为了理解MongoDB的名词,可以将其于关系型数据库进行对比: 一.文档 概述 文档是MongoDB的核心概念,是数据的基本单元,非常类似于关系数据库中的行.在MongoDB中,文档表示为键值对的一个 ...

  8. CookiesHelper

    /// <summary> ///CookiesHelper 的摘要说明 /// </summary> public class CookiesHelper { public ...

  9. vue1.0学习

    vue 一片html代码配合上json,在new出来vue实例 Demo:1 数据双向绑定(v-model="message",{{message}}) <div id=&q ...

  10. jquery源码解读 (摘自jQuery源码分析系列图书(pdf)) 持续更新

    1.总体架构 1.1自调用匿名函数 //自调用匿名函数 (function(window,undefined){ //jquery code})(window); 1.这是一个自调用匿名函数.第一个括 ...