匿名管道

1.进程通信的目的

    (1) 数据传输: 一个进程需要将它的数据传输给另一个进程
    (2) 资源共享: 多个进程之间共享同样的资源
    (3) 通知事件: 一个进程需要向另一个或一组进程发送消息, 通知它们发生了什么事情

2.管道

    管道是一种进程之间通信的一种方式, 我们把从一个进程连接到另一个进程的数据流叫做管道

3.匿名管道

    (1) 匿名管道的创建

int pipe(int fd[2]);
fd是一个文件描述符数组, fd[0] 代表读端, fd[1] 代表写端
返回值:成功过时返回0, 失败时返回错误代码
4.代码演示
//clientPipe.c
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<stdlib.h>int main()
{int wfd = open("mypipe", O_WRONLY);if(wfd == -1)//dakashibai{perror("open");exit(1);}char buf[1024];buf[0] = 0;ssize_t s;while(1){printf("Please Enter#");fflush(stdout);s = read(0, buf, sizeof(buf));if(s > 0)//成功读取{buf[s] = 0;write(wfd, buf, s);}else if(s <= 0)//读取失败{perror("read");exit(1);}}
}//serverPipe.c
#include<stdio.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<sys/types.h>int main()
{int fifo = mkfifo("mypipe", 0644);if(fifo == -1)//管道创建失败{perror("mkfifo");exit(1);}//打开管道int rfd = open("mypipe", O_RDONLY);if(rfd == -1)//打开失败{perror("open");exit(1);}//读管道数据char buf[1024];ssize_t s;while(1){buf[0] = 0;printf("Please wait ... \n");s = read(rfd, buf, sizeof(buf) -1);if(s > 0)//读到数据{buf[s] = 0;printf("client say# %s", buf);}else if(s == 0)//读完{printf("client quit, exit now\n");exit(0);}else//读取失败{perror("read");exit(1);}}close(rfd);return 0;
}

             这里写图片描述

5.站在文件描述符角度理解

这里写图片描述
这里写图片描述
    父进程先创建管道, 创建完管道,同时父进程打打开对应的读端和写端,接着父进程创建子进程, 由于子进程会继承父进程的特性, 因此子进程也会打开和父进程一样的读端和写端, 此时父子进程就看到了一份公共资源, 紧接着父进程将读端关闭, 子进程将写端关闭, 于是便可以父进程进行对数据的写,子进程只管从管道中读数据即可,于此父子进程合作完成读写工作.

6.管道读写规则

     (1) 当管道读端关闭, 写端还在继续写的时候此时操作系统会给写端发送一个 SIGPIPE 的信号,从而使得写端退出
     (2) 如果写端对应的描述符关闭, 读端则会正常退出.
     (3) 管道具有上限,当写到 PIPE_BUF 时, Linux 将不再保证其写入的原子性.
     (4) 注意匿名管道对应的两个进程之间一定是由血缘关系的

7. 管道特点

     (1) 管道具有单向性
     (2) 有血缘关系的进程之间才能进行通信(匿名管道)
     (3) 管道必须满足同步互斥关系(管道没有数据时,读端进程将会不读,阻塞等待, 当管道已经满的时候就不能对管道进行写了)
     (4) 管道的生命周期随进程
     (5) 管道提供字节流服务(从管道中一次读多少由操作系统决定, 即一次读写多少不确定)

8. 相关的几个概念

     (1) 数据不一致: 一个进程的读写影响到另外一个进程的读写
     (2) 临界资源: 两个进程看到的一份公共资源,并且一次只允许一个进程使用
     (3) 临界区: 进程访问临界资源的那段代码就叫做临界资源
     (4) 互斥: 各进程有时需要共享资源, 而且有些资源需要互斥访问, 因此进程之间竞争使用这些资源, 进程之间的这种关系叫做互斥
     (5) 进程访问资源的原子性: 进程在操作某些资源时要不做完, 要不不做, 中间不会收到如何其他进程的干扰.
     (6) 同步: 进程之间以一种比较安全的顺序访问资源, 这种安全机制就叫做同步
     (7) 管道自带同步互斥机制, 当管道中没有数据时父进程会等待子进程的退出

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384090.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

将信号量代码生成静态库以及动态库

1.信号量相关代码生成静态库 2.信号量相关代码生成动态库

C++11 标准新特性:Defaulted 和 Deleted 函数

https://www.ibm.com/developerworks/cn/aix/library/1212_lufang_c11new/index.html Defaulted 函数 背景问题 C 的类有四类特殊成员函数&#xff0c;它们分别是&#xff1a;默认构造函数、析构函数、拷贝构造函数以及拷贝赋值运算符。这些类的特殊成员函数负责创建、初始化、…

顺序表实现栈相关操作

1.栈的相关概念 栈是一种特殊的线性表, 其中只允许在固定的一端进行插入和删除元素.进行数据插入和删除的一端叫做栈顶, 另一端成为栈底. 不含任何元素的栈称为空栈, 栈又称为先进先出的线性表. 2. 顺序栈的结构 3. 顺序栈的具体操作 (1). 数据结构 typedef char SeqStackTyp…

双向带环带头结点的链表实现栈

1. 数据结构 利用带头结点带环的结点实现栈的相关操作.因此, 每一个结点包括了一个前驱, 一个后继, 还有一个数据成员 typedef char DLinkStackType;typedef struct DLinkStack {DLinkStackType data;struct DLinkStack* next;struct DLinkStack* prev; }DLinkStack;2. 初始化…

C++11 标准新特性:委派构造函数

https://www.ibm.com/developerworks/cn/rational/1508_chenjing_c11/index.html陈 晶2015 年 8 月 11 日发布WeiboGoogle用电子邮件发送本页面 1本文首先介绍了在委派构造函数提出之前类成员构造所面临的问题&#xff0c;再结合实例介绍了委派构造函数的用法&#xff0c;并说明…

顺序表实现队列

一. 队列相关概念 队列是只允许在一段进行插入元素, 在另一端进行删除元素的线性表,即只允许对队列进行尾插,头删的操作.队列具有先进先出, 后进后出的特性.          1.初始化 void SeqQueInit(SeqQue* q) {if(q NULL){return;//非法输入}q -> head 0;q -> …

链表实现队列

上篇博客是用顺序表实现队列, 现在用双向带头结点带环链表实现对队列的出队列, 入队列, 取队首元素, 以及销毁队列的相关操作 1.初始化链表 void DLinkQueInit(DLinkQue** q) {if(q NULL){return;//非法输入}if(*q NULL){return;//非法输入带头结点的链表至少有一个傀儡结点…

HDU - 1796——容斥原理+二进制枚举

【题目描述】 Now you get a number N, and a M-integers set, you should find out how many integers which are small than N, that they can divided exactly by any integers in the set. For example, N12, and M-integer set is {2,3}, so there is another set {2,3,4,…

信号的基本概念以及信号的产生

一. 信号产生的场景 1. 用户输入命令, 在shell 启动一个前台进程      2. 当用户按一下 Ctrl C 的时候,从键盘产生一个硬件中断      3. 此时CPU 正在执行这个进程的带代码, 则该进程的执行代码暂停执行, CPU 从用户态切换到内核态处理该硬件中断.      4. 中断…

信号的阻塞

一. 阻塞信号 1.信号的相关概念     (1) 递达: 实际执行信号的处理动作称为信号的递达     (2) 未决: 信号从产生到递达之间的过程叫做信号的未决     (3) 阻塞: 进程可以选择阻塞某个信号, 被阻塞的信号产生时将保持在未决状态, 直到进程解除该信号的屏蔽, 才…

信号的捕捉以及SIGCHLD信号

一. 信号的捕捉定义 用户提供一个处理函数, 要求内核在处理信号时必须切换到用户态,执行这个函数, 这种方式就叫做信号的捕捉 二. 图解信号的捕捉过程 1. 由上图可以看出,当处理信号的执行动作时用户自定义的时候,此时就需返回该函数去调用该函数, 这就叫做信号的捕捉. 以前我…

最小栈的实现

所谓最小栈, 就是当前栈顶元素最小, 我们可以这样做, 每次在入栈之前, 将待入栈元素与栈顶元素相比, 每次现将待入栈的元素先入栈, 再将带入栈的元素和较小的元素入栈, 这样就可以保证每次栈顶元素是最小元素. 在出栈的时候规定每次出栈两个元素,这样就可以保证在出栈之后栈顶元…

用C++实现单链表的创建、逆置和输出 的两种方法

http://blog.csdn.net/lfeng_coding/article/details/47300563 题目描述&#xff1a;在已知单链表头节点的情况下&#xff0c;设计算法逆置单链表并输出 方法一&#xff1a;采用首先将头节点指向空&#xff0c;让其变为尾节点&#xff0c;然后利用中间节点 p、q 将其后的节点一…

两个栈实现一个队列

利用两个栈实现一个队列思路是这样的. 首先这个队列包含两个栈, 然后一个栈用来入队列, 一个栈用来出队列 typedef struct QueBy2Stack {SeqStack input;SeqStack output; }QueBy2Stack; 1. 初始化 void QueBy2StackInit(QueBy2Stack* stack) {if(stack NULL){return;//非法…

Linux--线程死锁

http://blog.csdn.net/gebushuaidanhenhuai/article/details/73799824 线程为什会死锁&#xff1f;&#xff1f;“锁”又是什么东西&#xff1f;我们这篇博客主要讲一下为什么要给线程加锁&#xff0c;为什么会出现线程死锁&#xff0c;线程死锁怎么解决。 互斥锁 在我的上篇博…

两个队列实现一个栈

用两个队列实现一个栈的原理是这样的. 规定两个队列, 必须有一个队列是非空, 一个队列是空.每次入栈时必须往非空队列中入, 而每次出栈时, 必须将非空队列里的元素装到空队列中, 直到非空队列中只有一个元素时, 此时就将剩下的这个元素出栈即可. 而取栈顶元素时, 和出栈一样, 先…

Linux--生产者与消费者

http://blog.csdn.net/gebushuaidanhenhuai/article/details/74011636 基本概念 提到生产者和消费者&#xff0c;我们最有可能想到的是商店卖东西&#xff0c;顾客在货架上(缓冲区&#xff09;买东西。 生产者消费者问题&#xff0c;其实是一个多线程同步问题的经典案例。该问…

进程的挂起以及可重入函数

相关接口     pause 函数用于将进程挂起. 如果信号的处理动作是终止进程, 则进程终止, pause 函数没有返回值; 如果信号的处理动作是忽略, 则进程被挂起, pause函数不返回, 如果信号的处理动作是捕捉, 则调用信号处理动作之后pause 返回 -1.来看一段代码 #include<s…

gdb调试多进程程序

1.gdb下调试多进程程序只需要以下几条命令即可              除此之外还可以查看正在调试的进程 info inferiors, 同时也可以将当前正在调试的进程切换到另外一个进程中让其取运行     2.代码调试演示 #include<stdio.h> #include<stdlib.h> #…

关于memcpy和memmove两函数的区别

http://blog.csdn.net/caowei840701/article/details/8491836 [cpp] view plaincopy <p> 关于memcpy和memmove两个c标准库函数&#xff0c;其功能都是将一块内存区域中的指定大小内容复制到目标内存中&#xff0c;在翻阅c标准库实现的源代码我们发现他们是有区别的。&…