2在前面介绍过,进程之间交换信息的唯一途径就是传送打开的文件。可以经由fork或者exec来传送。这一章将介绍新的进程共享方式
每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程A把数据从用户空间拷到内核缓冲区,进程B再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信,如下图所示

不同进程间的通信本质:进程之间可以看到一份公共资源;而提供这份资源的形式或者提供者不同,造成了通信方式不同,而 pipe就是提供这份公共资源的形式的一种。
管道是由调用pipe函数来创建
#include <unistd.h>
int pipe (int fd[2]);
fd参数返回两个文件描述符,fd[0]指向管道的读端,fd[1]指向管道的写端。fd[1]的输出是fd[0]的输入。
 
管道是如何实现进程间的通信
(1)父进程创建管道,得到两个⽂件描述符指向管道的两端
 
(2)父进程fork出子进程,⼦进程也有两个⽂件描述符指向同⼀管道。
 
(3)父进程关闭fd[0],子进程关闭fd[1],即⽗进程关闭管道读端,⼦进程关闭管读写端(因为管道只支持单向通信)。⽗进程可以往管道⾥写,⼦进程可以从管道⾥读,管道是⽤环形队列实现的,数据从写端流⼊从读端流出,这样就实现了进程间通信。  
 
 
实现如下图所示

实现代码
int chapter15_5()
{
    int n;
    int fd[2];
    pid_t pid;
    char line[MAXLINE];
    if (pipe(fd) < 0)
    {
        printf("pipe error");
    }
    pid=fork();
    if (pid == 0)
    {
        close(fd[1]);
        n=read(fd[0],line,MAXLINE);
        write(STDOUT_FILENO,line,n);
    }
    else
    {
        close(fd[0]);
        write(fd[1],"hello world\n",12);
    }
}
在上面的代码中,是父进程关闭读通道,子进程关闭写通道。父进程向fd[1]中写入数据,子进程从fd[0]中读出数据并显示在终端上。同样的我们也可以子进程关闭读通道,父进程关闭写通道,由子进程来写入数据,父进程读取数据
 
管道读取数据的4种情况:
1 读端不读,写端一直写

2 写端不写,但是读端一直读

3 读端一直读,且fd[0]保持打开,而写端写了一部分数据不写了,并且关闭fd[1]。

如果一个管道读端一直在读数据,而管道写端的引⽤计数⼤于0决定管道是否会堵塞,引用计数大于0,只读不写会导致管道堵塞。

4 读端读了一部分数据,不读了且关闭fd[0],写端一直在写且f[1]还保持打开状态。

来看下这种异常的代码:

int chapter_15_5_1()

{

int fd[2];

int ret = pipe(fd);

if (ret == -1)

{

printf("pipe error\n");

return 1;

}

pid_t id = fork();

if (id == 0)

{

int i = 0;

close(fd[0]);

char child[20] = "I am a student";

while (i<10)

{

write(fd[1], child, strlen(child) + 1);

sleep(2);

i++;

}

}

else if (id>0)

{

close(fd[1]);

char msg[100];

int status = 0;

int j = 0;

while (j<5)

{

memset(msg,'\0',sizeof(msg));

ssize_t s = read(fd[0], msg, sizeof(msg));

if (s>0)

{

msg[s-1] = '\0';

}

printf("%s %d\n",msg,j);

j++;

}

close(fd[0]);

pid_t ret = waitpid(id, &status, 0);

printf("exit single(%d),exit(%d)\n",status & 0xff, (status >> 8) & 0xff);

}

else

{

printf("fork error\n");

return 2;

}

return  0;

}

在这段代码中,子进程关闭读端,每隔2秒向管道写数据,父进程关闭写端,当读了5次数据后就关闭读端。此时再往管道写数据则会报错。

如果一个管道的写端一直在写,而读端的引⽤计数是否⼤于0决定管道是否会堵塞,引用计数大于0,只写不读再次调用write会导致管道堵塞;

如果一个管道的读端一直在读,而写端的引⽤计数是否⼤于0决定管道是否会堵塞,引用计数大于0,只读不写再次调用read会导致管道堵塞;

而当他们的引用计数等于0时,只写不读会导致写端的进程收到一个SIGPIPE信号,导致进程终止,只写不读会导致read返回0,就像读到⽂件末尾⼀样。

linux c编程:管道的更多相关文章

  1. Linux系统编程—管道

    ▋****1. 管道的概念 管道,又名「无名管理」,或「匿名管道」,管道是一种非常基本,也是使用非常频繁的IPC方式. 1.1 管道本质 管道的本质也是一种文件,不过是伪文件,实际上是一块内核缓冲区, ...

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

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

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

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

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

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

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

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

  6. Linux 系统编程

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

  7. linux网络编程九:splice函数,高效的零拷贝

    from:http://blog.csdn.net/jasonliuvip/article/details/22600569 linux网络编程九:splice函数,高效的零拷贝 最近在看<Li ...

  8. linux —— shell 编程(编程语法)

    导读 本文为博文linux —— shell 编程(整体框架与基础笔记)的第4小点的拓展.(本文所有语句的测试均在 Ubuntu 16.04 LTS 上进行) 目录 再识变量 函数 条件语句 循环语句 ...

  9. linux shell编程总结

    linux shell编程总结 本周学习了unix/linux shell编程,参考的是<LINUX与UNIX Shell 编程指南>,David Tansley著:徐焱,张春萌等译,由机 ...

  10. Linux网络编程一站式学习

    提要 学过非常多遍计算机网络,依旧不会网络编程. 看完这篇文章之后就不会是这样了. 环境:Ubuntu14.04 64bit 何为Socket 是基于TCP/IP的网络应用编程中使用的有关数据通信的概 ...

随机推荐

  1. 改进xutils下载管理器,使其,在随意地方进行进度更新,以及其它状态监听操作

    1.前面在做下载进度监听.尝试过,通过加入 弱引用的View进度条,到相应的集合. 等到要进行更新进度的时候.通过Key 获取相应的VIew来进行更新 进度条.效果是达到了,可是我们怎样来监听其它的状 ...

  2. ionic准备之angular基础———服务provider 和 factory和service(9)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. springboot jpa | mybaits

    一.jpa: 1.jpa可以使用jpaRepository,@query的查询, 当然如果方法命名规范,可以不写sql代码 2.jpa可也使用EntityManager,通过@PersistenceC ...

  4. Spring MVC 学习笔记 spring mvc Schema-based configuration

    Spring mvc 目前支持5个tag,分别是 mvc:annotation-driven,mvc:interceptors,mvc:view-controller, mvc:resources和m ...

  5. (三)storm-kafka源代码走读之怎样构建一个KafkaSpout

    上一节介绍了config的相关信息,这一节说下,这些參数各自是什么.在zookeeper中的存放路径是如何的,之前QQ群里有非常多不知道该怎么传入正确的參数来new 一个kafkaSpout,其主要还 ...

  6. swift 可变參数

    func sumof(numbers:Int...)->Int{  var sum = 0;  for number in numbers{   sum+=number;  }  return ...

  7. ios侧滑返回:完美解决 interactivePopGestureRecognizer 卡住的问题

    interactivePopGestureRecognizer是iOS7推出的解决VeiwController滑动后退的新功能,虽然很实用,但是坑也很多啊(比如在rootViewcontroller下 ...

  8. Android下Sqlite的使用(9.7)

    1 http://blog.csdn.net/liuhe688/article/details/6715983 2 http://www.eoeandroid.com/thread-170715-1- ...

  9. docker pull net/http: TLS handshake timeout错误解决

    docker pull  net/http: TLS handshake timeout  出现这个错误,原因很明显,我们在围城里,有两种解决办法,一种是用梯子爬围墙,一种是用国内源,下面用国内源 e ...

  10. Maven环境下搭建SSH框架之Spring整合Struts2

    © 版权声明:本文为博主原创文章,转载请注明出处 1.搭建环境 Struts2:2.5.10 Spring:4.3.8.RELEASE 注意:其他版本在某些特性的使用上可能稍微存在差别 2.准备工作 ...