Linux学习记录--匿名沟通渠道
匿名沟通渠道
管道Linux最初支持Unix IPC其中的一种形式。具有下列特征:
1.管道是半双工。数据可以仅在一个方向流动;当双方需要沟通。建设两条管线需要。
2.仅仅能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);
什么是管道
管道对于管道两端的进程而言,就是一个文件。但它不是普通的文件,它不属于某种文件系统。而是自立门户,单独构成一种文件系统,而且仅仅存在与内存中。
数据的读出和写入
一个进程向管道中写的内容被管道还有一端的进程读出。写入的内容每次都加入在管道缓冲区的末尾。而且每次都是从缓冲区的头部读出数据。
管道的创建
#include int pipe(int fd[2]) |
管道两端可分别用描写叙述字fd[0]以及fd[1]来描写叙述,须要注意的是,管道的两端是固定了任务的。即一端仅仅能用于读,由描写叙述字fd[0]表示,称其为管道读端;还有一端则仅仅能用于写,由描写叙述字fd[1]来表示,
管道的规则
1. 当管道内容长度为0时,读端将处于堵塞状态,等待写端向管道写入内容
2. 当写端数据长度小于缓冲区长度时。数据将以原子性写入缓冲区。
对读进程来说:
3. 当写端被关闭时。全部数据被读出后,read返回0。
4. 当写端未被关闭时。全部数据被读出后。读端堵塞。
对写进程来说:
5. 当读端关闭时,如写端数据长度大于管道最大长度时,写完管道长度时。产生信号SIGPIPE后退出程序。
(以存入管道的数据读进程能够读取到)
6. 当读端未被关闭时。如写端数据长度大于管道最大长度时,写完管道长度时,写端将处于堵塞状态
规则分析1
- #include<unistd.h>
- #include<stdio.h>
- #include<string.h>
- #include<sys/types.h>
- #include<stdlib.h>
- #include<sys/wait.h>
- int main() {
- int fd[2];
- pid_t cid;
- if (pipe(fd) == -1) {
- perror("管道创建失败!
- ");
- exit(1);
- }
- cid = fork();
- switch (cid) {
- case -1:
- perror("子进程创建失败");
- exit(2);
- break;
- case 0:
- close(fd[1]);
- char message[1000];
- int num = read(fd[0], message, 1000);
- printf("子进程读入的数据是:%s,长度是=%d", message, num);
- close(fd[0]);
- break;
- default:
- close(fd[0]);
- char *writeMsg = "父进程写入的数据!
- ";
- sleep(10);//1
- write(fd[1], writeMsg, strlen(writeMsg));
- close(fd[1]);
- break;
- }
- return 0;
- }
[root@ Release 18$] ps -C processcomm -opid,ppid,stat,cmd
PID PPID STAT CMD
5973 2488 S /root/workspace/processcomm/Release/processcomm
5976 5973 S /root/workspace/processcomm/Release/processcomm
=>读端因为堵塞中。其所在进程(子进程)处于sleep状态
控制台输出
父进程工作PID=5973,PPID=2488
子进程工作PID=5976,PPID=5973
子进程读入的数据是:父进程写入的数据!
,长度是=27
规则分析2
- switch (cid) {
- case -1:
- perror("子进程创建失败");
- exit(2);
- break;
- case 0:
- printf("子进程工作PID=%d,PPID=%d\n", getpid(), getppid());
- break;
- default:
- printf("父进程工作PID=%d,PPID=%d\n", getpid(), getppid());
- close(fd[0]);
- const long int writesize=4000;
- char writeMsg[writesize];
- int i;
- for(i=0;i<writesize;i++)
- {
- writeMsg[i]='a';
- }
- int writenum=write(fd[1], writeMsg, strlen(writeMsg));
- printf("父进程写入的数据长度是=%d\n", writenum);
- close(fd[1]);
- wait(NULL);
- break;
- }
控制台输出
父进程工作PID=7072,PPID=2488
父进程写入的数据长度是=4001
子进程工作PID=7077,PPID=7072
规则分析3
- switch (cid) {
- case -1:
- perror("子进程创建失败");
- exit(2);
- break;
- case 0:
- printf("子进程工作PID=%d,PPID=%d\n", getpid(), getppid());
- close(fd[1]);
- char message[40001];
- int num = read(fd[0], message, 4001);
- printf("子进程读入的数据长度是=%d\n", num);
- num = read(fd[0], message, 4000);
- printf("子进程再次读入的数据长度是=%d", num);
- close(fd[0]);
- break;
- default:
- printf("父进程工作PID=%d,PPID=%d\n", getpid(), getppid());
- close(fd[0]);
- const long int writesize = 4000;
- char writeMsg[writesize];
- int i;
- for (i = 0; i < writesize; i++) {
- writeMsg[i] = 'a';
- }
- int writenum = write(fd[1], writeMsg, strlen(writeMsg));
- printf("父进程写入的数据长度是=%d\n", writenum);
- close(fd[1]);
- // wait(NULL);
- break;
- }
[root@ Release30$] ps -C processcomm -o pid,ppid,stat,cmd
PID PPID STAT CMD
=>读写进程都已退出
控制台输出
父进程工作PID=8004,PPID=2488
父进程写入的数据长度是=4001
子进程工作PID=8009,PPID=1
子进程读入的数据长度是=4001
子进程再次读入的数据长度是=0
规则分析4
- switch (cid) {
- case -1:
- perror("子进程创建失败");
- exit(2);
- break;
- case 0:
- printf("子进程工作PID=%d,PPID=%d\n", getpid(), getppid());
- char message[40001];
- int num = read(fd[0], message, 4001);
- printf("子进程读入的数据长度是=%d", num);
- num = read(fd[0], message, 4000);
- printf("子进程再次读入的数据长度是=%d", num);
- break;
- default:
- printf("父进程工作PID=%d,PPID=%d\n", getpid(), getppid());
- close(fd[0]);
- const long int writesize = 4000;
- char writeMsg[writesize];
- int i;
- for (i = 0; i < writesize; i++) {
- writeMsg[i] = 'a';
- }
- int writenum = write(fd[1], writeMsg, strlen(writeMsg));
- printf("父进程写入的数据长度是=%d\n", writenum);
- close(fd[1]);
- break;
- }
[root@ Release29$] ps -C processcomm -o pid,ppid,stat,cmd
PID PPID STAT CMD
7916 1 S /root/workspace/processcomm/Release/processcomm
=>读进程堵塞
控制台输出:
父进程工作PID=7914,PPID=2488
父进程写入的数据长度是=4001
子进程工作PID=7916,PPID=1
规则分析5
- switch (cid) {
- case -1:
- perror("子进程创建失败");
- exit(2);
- break;
- case 0:
- printf("子进程工作PID=%d,PPID=%d\n", getpid(), getppid());
- close(fd[1]);
- char message[65535];
- int num = read(fd[0], message, 65535);
- printf("子进程读入的数据长度是=%d", num);
- close(fd[0]);
- break;
- default:
- printf("父进程工作PID=%d,PPID=%d\n", getpid(), getppid());
- close(fd[0]);
- const long int writesize = 80000;
- char writeMsg[writesize];
- int i;
- for (i = 0; i < writesize; i++) {
- writeMsg[i] = 'a';
- }
- int writenum = write(fd[1], writeMsg, strlen(writeMsg));
- printf("父进程写入的数据长度是=%d\n", writenum);
- close(fd[1]);
- wait(NULL);
- break;
- }
[root@ Release25$] ps -C processcomm -o pid,ppid,stat,cmd
PID PPID STAT CMD
=>全部进程都以退出
控制台输出
父进程工作PID=7776,PPID=2488
子进程工作PID=7778,PPID=7776
子进程读入的数据长度是=65535
规则分析6
- switch (cid) {
- case -1:
- perror("子进程创建失败");
- exit(2);
- break;
- case 0:
- printf("子进程工作PID=%d,PPID=%d\n", getpid(), getppid());
- break;
- default:
- printf("父进程工作PID=%d,PPID=%d\n", getpid(), getppid());
- const long int writesize=80000;
- char writeMsg[writesize];
- int i;
- for(i=0;i<writesize;i++)
- {
- writeMsg[i]='a';
- }
- int writenum=write(fd[1], writeMsg, strlen(writeMsg));
- printf("父进程写入的数据长度是=%d\n", writenum);
- wait(NULL);
- break;
- }
父进程工作PID=7309,PPID=2488
子进程工作PID=7314,PPID=7309
[root@ Release24$] ps -C processcomm -o pid,ppid,stat,cmd
PID PPID STAT CMD
7309 2488 S /root/workspace/processcomm/Release/processcomm
7314 7309 Z [processcomm]<defunct>
管道代码举例
1. 当发送信息小于管道最大长度
- #include<unistd.h>
- #include<stdio.h>
- #include<string.h>
- #include<sys/types.h>
- #include<stdlib.h>
- #include<sys/wait.h>
- int main() {
- int fd[2];
- pid_t cid;
- if (pipe(fd) == -1) {
- perror("管道创建失败!");
- exit(1);
- }
- cid = fork();
- switch (cid) {
- case -1:
- perror("子进程创建失败");
- exit(2);
- break;
- case 0:
- printf("子进程工作PID=%d,PPID=%d\n", getpid(), getppid());
- close(fd[1]);
- char message[1000];
- int num;
- do {
- num = read(fd[0], message, 1000);
- printf("子进程读入的数据长度是=%d\n", num);
- } while (num != 0);
- close(fd[0]);
- break;
- default:
- printf("父进程工作PID=%d,PPID=%d\n", getpid(), getppid());
- close(fd[0]);
- const long int writesize = 37;
- char writeMsg[writesize];
- int i;
- for (i = 0; i < writesize-1; i++) {
- writeMsg[i] = 'a';
- }
- writeMsg[writesize-1]='\0';
- int writenum = write(fd[1], writeMsg, strlen(writeMsg)+1);
- printf("父进程写入的数据长度是=%d\n", writenum);
- close(fd[1]);
- break;
- }
- return 0;
- }
2. 当发送信息大于管道最大长度
此样例主要应该规则6。当发送信息大于管道长度时且写进程在未所有将新数据写入管道中。写进程处于堵塞状态。直到所有数据写入管道
- int main() {
- int fd[2];
- pid_t cid;
- if (pipe(fd) == -1) {
- perror("管道创建失败。");
- exit(1);
- }
- cid = fork();
- switch (cid) {
- case -1:
- perror("子进程创建失败");
- exit(2);
- break;
- case 0:
- printf("子进程工作PID=%d,PPID=%d\n", getpid(), getppid());
- close(fd[1]);
- char message[1000];
- int num;
- do {
- num = read(fd[0], message, 1000);
- printf("子进程读入的数据长度是=%d\n", num);
- }while(num!=0);
- close(fd[0]);
- break;
- default:
- printf("父进程工作PID=%d,PPID=%d\n", getpid(), getppid());
- const long int writesize = 80000;
- char writeMsg[writesize];
- int i;
- for (i = 0; i < writesize-1; i++) {
- writeMsg[i] = 'a';
- }
- writeMsg[writesize-1]='\0';
- int writenum = write(fd[1], writeMsg, strlen(writeMsg)+1);
- printf("父进程写入的数据长度是=%d\n", writenum);
- close(fd[0]);
- close(fd[1]);
- break;
- }
- return 0;
- }
3. 写进程多次写入
此例应用规则6,防止多次写入,写入数据长度管道最大长度
- int main() {
- int fd[2];
- pid_t cid;
- if (pipe(fd) == -1) {
- perror("管道创建失败。");
- exit(1);
- }
- cid = fork();
- switch (cid) {
- case -1:
- perror("子进程创建失败");
- exit(2);
- break;
- case 0:
- printf("子进程工作PID=%d,PPID=%d\n", getpid(), getppid());
- close(fd[1]);
- char message[1000];
- int num;
- do {
- num = read(fd[0], message, 1000);
- if (num > 0) {
- printf("子进程读入的数据长度是=%d %s\n", num, message);
- }
- } while (num != 0);
- close(fd[0]);
- break;
- default:
- printf("父进程工作PID=%d,PPID=%d\n", getpid(), getppid());
- const long int writesize = 10;
- char writeMsg[writesize];
- int i;
- for (i = 0; i < writesize - 1; i++) {
- writeMsg[i] = 'a';
- }
- writeMsg[writesize - 1] = '\0';
- int writenum = write(fd[1], writeMsg, strlen(writeMsg));
- printf("父进程写入的数据长度是=%d\n", writenum);
- char *newmsg = "helloworld";
- writenum = write(fd[1], newmsg, strlen(newmsg) + 1);
- printf("父进程再次写入的数据长度是=%d\n", writenum);
- close(fd[0]);
- close(fd[1]);
- break;
- }
- return 0;
- }
4. 兄弟间的管道通讯
- int main() {
- int fd[2];
- pid_t cid, did;
- if (pipe(fd) == -1) {
- perror("管道创建失败!");
- exit(1);
- }
- cid = fork();
- switch (cid) {
- case -1:
- perror("兄进程创建失败");
- exit(2);
- break;
- case 0:
- printf("兄进程工作PID=%d,PPID=%d\n", getpid(), getppid());
- close(fd[1]);
- char message[1000];
- int num;
- do {
- num = read(fd[0], message, 1000);
- if (num > 0) {
- printf("兄进程读入的数据长度是=%d,%s\n", num, message);
- }
- } while (num != 0);
- close(fd[0]);
- break;
- default:
- did = fork();
- if (did == 0) {
- printf("弟进程工作PID=%d,PPID=%d\n", getpid(), getppid());
- const long int writesize = 10;
- char writeMsgs[writesize];
- int i;
- for (i = 0; i < writesize - 1; i++) {
- writeMsgs[i] = 'a';
- }
- writeMsgs[writesize - 1] = '\0';
- int writenum = write(fd[1], writeMsgs, strlen(writeMsgs) + 1);
- printf("弟进程写入的数据长度是=%d\n", writenum);
- close(fd[0]);
- close(fd[1]);
- } else if (did == -1) {
- perror("弟进程创建失败!");
- exit(3);
- }
- break;
- }
- return 0;
- }
5. 父子双通道管道通讯
- int main() {
- int fd[2], backfd[2];
- pid_t cid;
- if (pipe(fd) == -1) {
- perror("管道创建失败!");
- exit(1);
- }
- if (pipe(backfd) == -1) {
- perror("管道创建失败!");
- exit(2);
- }
- cid = fork();
- switch (cid) {
- case -1:
- perror("子进程创建失败");
- exit(2);
- break;
- case 0:
- printf("子进程工作PID=%d,PPID=%d\n", getpid(), getppid());
- close(fd[1]);
- char message[10000];
- int num;
- do {
- num = read(fd[0], message, 10000);
- printf("子进程读入的数据长度是=%d\n", num);
- } while (num != 0);
- close(fd[0]);
- close(backfd[0]);
- char *msg1 = "消息返回成功啊!
- ";
- write(backfd[1], msg1, strlen(msg1) + 1);
- close(backfd[1]);
- break;
- default:
- printf("父进程工作PID=%d,PPID=%d\n", getpid(), getppid());
- const long int writesize = 80000;
- char writeMsg[writesize];
- int i;
- for (i = 0; i < writesize - 1; i++) {
- writeMsg[i] = 'a';
- }
- writeMsg[writesize - 1] = '\0';
- int writenum = write(fd[1], writeMsg, strlen(writeMsg) + 1);
- printf("父进程写入的数据长度是=%d\n", writenum);
- close(fd[0]);
- close(fd[1]);
- close(backfd[1]);
- char msg2[1000];
- int num1 = read(backfd[0], msg2, 1000);
- printf("返回消息:%s", msg2);
- close(backfd[0]);
- break;
- }
- return 0;
- }
Linux学习记录--匿名沟通渠道的更多相关文章
- linux学习记录(第六章、Linux 的文件权限与目录配置)
书看的是鸟哥的私房菜,系统用的是centos.被微软坑了N年才发现linux才是王道. 在这里记录些学习的记录.备忘
- Linux 学习记录 一(安装、基本文件操作).
Linux distributions主要分为两大系统,一种是RPM方式安装软件的系统,包括Red Hat,Fedora,SuSE等都是这类:一种则是使用Debian的dpkg方式安装软件的 ...
- Linux 学习记录一(安装、基本文件操作).
Linux 名字的由来,是当时作者将初版的 Linux 发布在网上,供别人下载完善,而那个核心文件夹就叫 Linux,就这么叫着了.而为什么 Linux 的吉祥物是一只企鹅呢?是因为当时大家要发行稳定 ...
- Linux学习记录
---恢复内容开始--- linux与unix的关系 linux是借鉴了unix设计思想,也称linux位类unix系统. Linux常用命令 1.命令基本格式 命令[选项][参数] 注意:个别命令不 ...
- Linux 学习记录
整理学习Linux操作系统遇到的不理解的概念.逐个进行补充.我们用的版本是CentOs. what's the gcc? what's the yum? what's the wget?
- Linux学习记录--命名管道通信
命名管道通信 什么是命名管道 一个主要的限制是,它是匿名管道的应用还没有名字,因此,只有它可以用于进程间通信的方式与亲缘关系.在命名管道(named pipe或FIFO)提出后,该限制得到了克服.FI ...
- Linux 学习记录 20170218
一.Linux 硬件查看命令 ----/proc 文件系统是一种内核和内核模块用来向进程(process) 发送信息的机制.我们可以从这个文件里获取到系统的相关信息. 1.显卡信息dmesg ...
- linux学习记录.1.安装
最近想了想决定开始学习linux. 在百度了一番后开始了安装,虚拟机VirtualBox,ubuntu. 基于VirtualBox虚拟机安装Ubuntu图文教程: http://blog.csdn.n ...
- Linux学习记录(一)
1.Linux的简介 1.1.Linux的概述 Linux是基于Unix的开源免费的操作系统,由于系统的稳定性和安全性几乎成为程序代码运行的最佳系统环境.Linux是由Linus Torvalds(林 ...
随机推荐
- 设计模式(四)原型模式Prototype(创建型)
设计模式(四)原型模式Prototype(创建型) 1. 概述 我们都知道,创建型模式一般是用来创建一个新的对象,然后我们使用这个对象完成一些对象的操作,我们通过原型模式可以快速的创建一个对象 ...
- myeclipse自动生成注释
myeclipse自动生成注释 在使用Eclipse编写Java代码时,自动生成的注释信息都是按照预先设置好的格式生成的,例如其中author的属性值. 我们可以在Eclipse中进行设置自己希望显示 ...
- 在cmd窗口中查询android的sqlite3数据库表之步骤
本文主要是写了一个android程序对sqlite3中数据库的employee表的插入.删除的操作,然后在cmd窗口中用sql命令查询employee表的操作过程. 1.第一步:首先把程序写好. 1. ...
- Shell中的if else语句小演示
安安静静学习小shell,今天看到if else 喽~ 下面这个脚本是判断用户执行脚本的参数,如果是hello的话,就显示how are you 如果什么都没有,就提示输入 如果参数不是hello,就 ...
- jquery分页
//分页插件 /** 2015-12-7 **/ (function($){ var ms = { init:function(obj,args){ return (function(){ ms.fi ...
- 工具类CTools实现字符编码转换和获取当前路径
class CTools { public: CTools(void); public: ~CTools(void); public: static std::string UNICODE_to_UT ...
- java--从控制台读入一些数据
学一些东西应该,学以致用: 现在我开始使用流的办法从控制台读取数据 import java.io.*; public class Demo2{ public static void main(Stri ...
- 06-IOSCore - KVC、CoreData
一. KVC 1. KVC 使用前:黯淡无光 if ([keyPath isEqualToString:@"name"]) { self.labelName.text = self ...
- JVM调优总结(七)-典型配置举例1
以下配置主要针对分代垃圾回收算法而言. 堆大小设置 年轻代的设置很关键 JVM中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制:系统的可用虚拟内存限制:系统的可用物理 ...
- 华为OJ:计算两个自然时间相加
按要求一步步做就好 import java.util.Scanner; public class dateAdd { public static void main(String args[]){ S ...